Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
LangChain4jを使った生成AIシステム設計パターン 〜 Javaで構築する最新アーキテクチャ
Search
鏡味秀行
October 26, 2024
3
700
LangChain4jを使った生成AIシステム設計パターン 〜 Javaで構築する最新アーキテクチャ
JJUG CCC 2024 Fall のセッション資料です。
デモは以下です
https://github.com/hide212131/langchain4j-demo
鏡味秀行
October 26, 2024
Tweet
Share
More Decks by 鏡味秀行
See All by 鏡味秀行
話題のGraphRAG、その可能性と課題を理解する
hide212131
4
1.9k
JHipsterで爆速かつ堅牢なエンタープライズ Spring Boot 開発を実現する
hide212131
0
670
Featured
See All Featured
Designing for Performance
lara
604
68k
Building an army of robots
kneath
302
43k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Building Adaptive Systems
keathley
38
2.3k
Fireside Chat
paigeccino
34
3k
It's Worth the Effort
3n
183
27k
4 Signs Your Business is Dying
shpigford
180
21k
The Art of Programming - Codeland 2020
erikaheidi
52
13k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
28
2k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
Why Our Code Smells
bkeepers
PRO
334
57k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Transcript
LangChain4jを使った生成AIシ ステム設計パターン 〜 Javaで構築する最新アーキテクチャ 経営企画本部 AI推進室 鏡味秀行 1
自己紹介 鏡味(かがみ) 秀行 (51歳) 現在: 自社の生成AIの普及展開 Java歴: Hotjava(‘95)~SI案 件15年ほど JHipsterで昨年JJUG登壇
日曜プログラミング、生成AI、 緑黄色社会、ドラム 2
本日のテーマ 生成AIを使ったシステムのアーキテクチャを学ぶ LangChain4jを通じてJava言語による生成AIシステムの 構築方法を理解 生成AIシステムの設計パターンを習得し今後の開発に活か せる 3
アジェンダ LangChain4jとLLMアーキテクチャ (15分) LLM抽象化/ Structured Outputs/ Function Calling RAG (Retrieval-Augmented
Generation) (15分) Naive RAG/ Advanced RAG AIエージェント (10分) まとめとQ&A (5分) 4
軽めのデモ あなたはLangChain4jで作られたエージェントです。 これからJJUG(ジェイジャグ)の会場でLangChain4jのセ ッションをします。 会場にいる人に自己紹介と現在時刻を伝えてください。 あなたが時刻を知っていることは珍しいので、そのこと も伝えてください。 最後に短くご挨拶をしてください。 “ “
5
デモ環境 10/18にOpenAIから出たAudio generation(従来のテキ スト用のAPIに音声も付く)をLangChain4jへQuickHack LangChain4jエージェントにて、時刻取りつつ挨拶 VSCodeでrapaio-jupyter-kernel実行 Java用のJupyter Kernel JShell実行、repo, dependency
を記述可能 6
会場の方へヒアリング システム開発をしていてLLMフレームワークを組み込んで いる方 それをJavaで開発されている方 7
LangChain4j Java用のLLMフレームワーク Python/JavaScriptの LangChainに触発 広範囲な機能をアクティブに 多様なモデルやストア対応 様々なツールの提供 SpringやQuarkusとの統合 8
その他のJavaのフレームワーク Spring AI Springファースト TestContainers周りの充実 Semantic Kernel MSのPlatformのサポート C#, Python
→ Javaポーティング 9
LLM FWのアーキテクチャ 紹介するもの: LangChain4jの他 Spring AI, Semantic Kernel for Java
など他でもサポートしている機能 ( 以降は一番メジャーなOpenAI社の機能名で説明) 1. LLMモデルなどのAPI抽象化 2. 構造データ出力 (Structured Ouputs ) 3. 関数呼び出し(Function Calling) 10
1. APIの抽象化 対応モデル: OpenAI, Azure OpenAI, Anthropic, Gemini, Ollama, etc...
以下 ️ 以外は共通 ChatLanguageModel model = OpenAiChatModel.builder() // ️ プロバイダー .apiKey("api key") // ️ APIキー .modelName(GPT_4_O_MINI) // ️ LLMモデル .build(); String answer = model.generate("「こんにちは」と言ってください"); System.out.println(answer); // → こんにちは 11
ストリーミング(流れるような文字) StreamingChatLanguageModel model = OpenAiStreamingChatModel.builder()...; model.generate("皆さんへ挨拶を一言で", new StreamingResponseHandler<AiMessage>() { //
コールバック @Override public void onNext(String token) { System.out.print(token + "|"); // |皆|さん|、|こんにちは|!| } @Override public void onComplete(Response<AiMessage> response) { } @Override public void onError(Throwable error) { } }); 12
2. Structured Outputs 天気 本⽇10/28の 天気は 曇りです。 10/28 曇り Structured
Outputs 13
2. Structured Outputs 非構造化データ から 構造データ を抽出 LangChain4jでは Structured Data
Extraction と呼 ばれる 天気 本⽇10/28の 天気は 曇りです。 10/28 曇り Structured Outputs 14
取りたい構造データの宣言 record WeatherInfo(LocalDate date, String weather) {}; 処理のインターフェースを宣言 interface WeatherForecast
{ // AiServices @SystemMessage("天気の情報を取得") WeatherInfo getWeatherInfo(String text); } 15
LLMモデルの作成 ChatLanguageModel strictModel = OpenAiChatModel.builder() .responseFormat("json_schema") // JSONスキーマ出力を強制する .strictJsonSchema(true) //
JSONスキーマ出力を強制する .build(); インスタンス化して実行 WeatherForecast forecast = AiServices.create(WeatherForecast.class, strictModel); WeatherInfo info = forecast.getWeatherInfo("明日(2024/10/28)の天気は曇りです。"); // 実行 System.out.println(info); // WeatherInfo[date=2024-10-27, weather=曇り] 16
2. Structured Outputs 欲しいJavaの型をJSON Schemaに変換して送信 LLMにスキーマを認識してもらえてエラー率が減る 部品として小回りがきく Pythonでも Instructor, Outlines
が好みの方も Pydantic(データのバリデーションや型ヒントの提 供)とJSON Schemaとの連携 ハルシネーションは起こしてしまうので対策は必須 17
AiServices (LangChain4j 固有名称) 18
Structured Outputs と AiServices Weather String 天気 10/28 曇り Weather
AiService Code ⽂字から天気情報 を 抽出するよ "本⽇10/28の天 気は曇りです" 19
AiServices による通常の対話 こんにちは。 なにかお⼿伝いできますか︖ String String こんにちは︕ Human Assistant AiService
質問に 答えるよ 20
AiServices LangChain4jの高レベルの抽象化API 概念的にはエージェント(あとの方でお話) 基本機能: Structured Outputs 機能を持つ対話型API 通常の対話 String型 →
String型 JPAのO/Rマッピングに似ている 機能のインジェクションで、エージェント能力強化 21
3. Function Calling 14:30です String String ⽇本は今何時ですか︖ Human Timekeeper AiService
LocalDateTime String 14:30 Clock #getCurrentTime (String zoneId) 時刻来たかぁ… 関数に頼ろう Asia/Tokyo 22
3. Function Calling LLMに用意された関数を実行するかを判断してもらう LLMが考えるのは 関数名 と 引数 のみ。実行はLLMの呼び 出し側で行う。
呼び出され側で行う Assistant API とは別モノ LangChain4jでは Tools と呼ばれる @Tool がついたメソッドを呼び出す 23
AiSerivices (処理のインターフェース) 宣言 interface TimeKeeper { @SystemMessage("現在の時刻を何時何分の形式で答えてください") String ask(String question);
} Function (Tool) の宣言 class Clock { // Function群 (Tools) @Tool // 呼び出したいFunction (Tool) public LocalDateTime getCurrentTime(String timeZoneId) { return LocalDateTime.now(ZoneId.of(timeZoneId)); } } 24
インスタンス化 TimeKeeper timeKeeper = AiServices.builder(TimeKeeper.class) .chatLanguageModel(model) .tools(new Clock()) // 関数(ツール)群の注入
.build(); 実行 String answer = timeKeeper.ask("今何時?"); System.out.println(answer); // 例: "現在の時刻は16時58分です" 25
Function Calling の使用場面 LLMに足りない機能を補う用途に使う 複雑な計算や統計分析、時制や地理を含む話題など LLMに制御を委ねてよい場合に使う 制御を自前でしたければ Structured Outputs を活用
LLMの処理結果を構造データで返してもらう データを見て制御を行う 26
⾃分は知らないので 外部に問い合わせよう。 結果から回答⽂は作ろう (専⾨的な回答) (専⾨的な質問) Human LLMに無い 専⾨的な 情報 問い合わせ
専⾨情報 AiService RAG 27
RAG (Retrieval-Augmented Generation) 専門知識など、LLMが知らない情報を外部より能力強化 多くは検索エンジンと組み合わせ 自然言語と相性のよいベクター検索が人気 外部情報その他: ネットの情報, RDB, GraphDB
様々な手法が日々考案(裏を返せば期待と結果のギャップ が大きい) 28
(専⾨的な回答) (専⾨的な質問) Human Vector DB Document RAG Pipline Query embedding
Chunked Txt Vec[12,-34,... Vec[11,-33,... Chunked Txt Naive RAG (Naive: 普通の) 29
Indexing ( RAG Pipiline ) (引用: https://docs.langchain4j.dev) 30
Indexing ( RAG Pipiline ) テキストを裁断してテキストチャンクに parsing, splitting, chunking テキストチャンクの意味をベクトル化
embedding DBに保存 indexing (専⾨的な回答) (専⾨的な質問) Human Vector DB Document RAG Pipline Query embedding Chunked Txt Vec[12,-34,... Vec[11,-33,... Chunked Txt 31
従来のETL(Extract/Transform/Load)ほぼ同様の概念 LLMシステムでは、より非構造データ・自然言語を対象と する傾向が強まる LlamaIndex の RAG Pipiline より データの取得(Load the
data) データの変換(Transform the data) データ索引格納(Index and store the data) 32
// parsing: RAGで使うドキュメントを読む DocumentParser documentParser = new TextDocumentParser(); Document document
= FileSystemDocumentLoader.loadDocument(toPath(documentPath), documentParser); // splitting, chunking: ドキュメントを300byteごとにチャンク分割 DocumentSplitter splitter = DocumentSplitters.recursive(300, 0); List<TextSegment> segments = splitter.split(document); 33
// embedding: チャンクの数分、float[385]のembeddingを作成 EmbeddingModel embeddingModel = new BgeSmallEnV15QuantizedEmbeddingModel(); List<Embedding> embeddings
= embeddingModel.embedAll(segments).content(); // indexing: インメモリストアに保存 EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>(); embeddingStore.addAll(embeddings, segments); 34
ローダー・パーサーのバリエーション DocumentLoader: Amazon S3, Azure Blob Storage, Google Cloud Storage,
File System, URL,etc... DocumentParser: Text, Apache Tika (MSOffice(POI) / PDF(PDFBox)) Tikaがサポートするフォーマット https://tika.apache.org/3.0.0-BETA2/formats.html 構造はシンプルなので独自実装も十分可能 35
Querying (引用: https://docs.langchain4j.dev) 36
Querying 質問の意味をベクトルで数値化する embedding 類似の意味を持つ情報を取り出す retrive 抽出した情報をLLMが整理して回答する generation (専⾨的な回答) (専⾨的な質問) Human
Vector DB Document RAG Pipline Query embedding Chunked Txt Vec[12,-34,... Vec[11,-33,... Chunked Txt 37
Injection Content Retriever Human VectorDB Query embedding AiService AiServiceでRAG 38
// コンテンツ取得担当(Retriever)を用意する ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder() .embeddingStore(embeddingStore) // ストアの注入 .embeddingModel(embeddingModel)
// モデルの注入 .build(); 39
// 質問回答アシスタントを用意する(自前で定義) public interface Assistant { String answer(String query); //
質問したら回答 } // アシスタントのプロキシを作成 Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(chatLanguageModel) // 回答作成用モデル .contentRetriever(contentRetriever) // Retrieverの注入 .build(); // Retrieve-Argumented Generation: 質問するとドキュメントを検索して回答 String agentAnswer = assistant.answer(userQuery); 40
Retrieval Argmentor Injection Content Retriever Human AiService Query Transformer Content
Aggregator Query Router Content Injector Advanced RAG 41
LangChain4jにおけるサポート RetrievalAugmentor: RAGプロセス全体を管理・制御 QueryTransformer : ユーザークエリを最適化 QueryRouter: 複数のRetrieverにクエリを振り分け ContentRetriever: ソースから情報取得
ContentAggregator: 取得したコンテンツを集約整理 ContentInjector: 取得したコンテンツをLLMのプロンプ トに挿入 42
QueryTransformer (専⾨的な回答) (専⾨的な質問) Human VectorDB Query embedding Vec[11,-33,... Query Transformer
(ヒットしやすい 質問) 43
QueryTransformer ベクター検索でヒットさせるため、質問を回答に近づける 質問と回答が意味的に近い「わけではない」 例:「東京の観光スポットは?」→ 「東京で最も訪れる価 値のある観光地」「東京における観光客に人気の名所」 「東京都内の有名な見どころ」 44
ContentRetriever: Text-to-SQL SQL Content Retriever Human RDB AiService ⽇本の都市を… Text
to SQL ”SELECT city FROM ... [東京, 神奈川,…] 東京や神奈川が... 45
Text-to-SQL ContentRetriever の一つ 自然言語からSQLを生成してRDBへ問い合わせ LangChain4jではSqlDatabaseContentRetrieverで試 験実装 自然言語クエリの解釈、SQLの生成と実行、エラー処理 から結果の整形して再実行 46
Text-to-SQLの様々な手法 自然言語→LLMが固定されたSQLを選択 自然言語→SQLテンプレート+LLM抽出パラメータ 自然言語→LLMがクエリの自動生成 スキーマや制約条件をLLMに与えて生成 その他、処理時間計測して最適化する例: Architectural Patterns for Text-to-SQL:
Leveraging LLMs for Enhanced BigQuery Interactions 47
セマンティックレイヤー 概念的には「ビジネスドメインの意味を もたせる層」「人間とデータの仲介」 Text-to-SQLにおける「自然言語」と 「SQLやデータ」 LangChain4j では AiService 48
AIエージェント 49
生成AIのハイプ・サイクル 引用: Gartner、「生成AIのハイプ・サイクル:2024年」を 発表 より 50
AIエージェントとはなにか ユーザの代理として自律的(プロアクティブ)に実行する 実行計画を自分で立てる 自ら実行する 反省し学習し適応する 51
AIエージェントはなぜ必要? 複雑で動的な問題の自律的解決 ビジネス環境の不確実性が高く、全てを事前に予測困難 状況に応じて臨機応変にスケーラブルに対応 できることはAIに委譲し、限られた人的リソースは創造的 で価値の高いことに使いたい 52
Agentic Design Patterns https://www.deeplearning.ai/ (Andrew Ng先生)より リフレクション: LLMの自己評価、性質の異なるLLMによ る相互評価、改善し再実行 ツールの利用:
外部ツールやAPIの活用(Function Calling やRAG) 計画と実行: 目標設定とタスク分割 マルチエージェント: エージェント同士の協力でタスク実 行 53
START END Coding Test Code Test Comp? 計画と実行 LangChainのブログ'Planning for
Agents'より 「PDCAプロセスをイチから考えて」 のLLMへの丸投げは今は辛み 人間がより具体化する必要 ドメイン固有の認知アーキテクチャ 状況把握と指示→状態遷移マシン ブログでは LangGraph を推奨 54
マルチエージェント DeepLearning.AIのAgentic Design Patterns Part 5, Multi-Agent Collaborationより 一つのLLMよりも、多様な意見を持つLLMに議論させたほ うが良い推論ができる
LLMは人間と同じで、長く煩雑で雑多な指示が苦手 役割ごとに細分化する 例)システムプロンプトで「あなたは◦◦のエキスパー トです」を複数立てる 55
LangChain4jでAgent こいつです→AiServices 自律的に判断して行動 外部情報取得 Function Calling, RAG 今後よりエージェント対応していくと予想 計画と実行のための状態遷移マシン 発展途上だが
LangGraph4j 56
LangChain4j + LangGraph4j Judge! Pros Cons START END Debate! 57
アーキテクチャスタイル LLMをツールとして使うか、エージェント として使うか 制御を手前か奥か Weather String 天気 10/28 曇り Weather
AiService Code ⽂字から天気情報 を 抽出するよ "本⽇10/28の天 気は曇りです" Retrieval Argmentor Injection Content Retriever Human AiService Query Transformer Content Aggregator Query Router Content Injector 58
本日説明しきれなかったところ システム評価と改善 LLMの出力品質を評価し最適化を行うフィードバックル ープの構築 Javaではスタンダートなものは無く、しばらくはPython などのツールを使っていくことに 59
Java+LLMについての思い 舞台は整っている: 環境は整備され学習コストも低い JavaがあればJavaに: エンタープライズ系、既存システム のエンハンス 溜めたスキル活かす: 皆さまがこれまで習得したスキルが むしろ大事、そのままLLMシステムに活かせる LangChain4j:
オススメですが、あくまで一つの代表例。 他のフレームワークも触っていただければ ️ 60
Spring Boot + LangChain4j 手軽にSpring BootでLangChain4jを試したかったら 拙作の JHipster LLM も触ってみてください
https://github.com/hide212131/generator-jhipster-llm 以下のコマンドで実行環境ができます。 jhipster-llm generate-sample sample --llm-framework langchain4j 61
Q&A 62
ご清聴ありがとうございました! 63