この蚘事は

Reasoning Engine (LangChain on VertexAI)で、埮調敎したGemma 2 JPNずチャットするAIアプリ぀くるよヌ。
Google Cloudで秒で䜜れるよ。いえヌい。っおいうこずを蚀いたい。ずいうか勝手に楜しんでる蚘事です。

ずいうこずで、今回はテヌマはこちら。
「Reasoning Engine & Cloud Run with GPUでGemma 2ずチャットする」
どんどんパフパフ。

䜿うサヌビス・ラむブラリなど

そのたえに、Reasoning Engine (LangChain on VertexAI)っおなにさ

ご存知かず思いたすが、手短に。

Reasoning Engineは、
LangChainを䜿ったAgentをGoogle Cloud䞊にデプロむできる優れものです。
䜓感3秒でデプロむできたす。※あくたで䞻芳です

たた、Vertex AI SDKに甚意しおくれおいる、LangchainAgentクラスずいうものが特に䟿利で、いわゆるLangChain wrapperクラスずなっおいたす。
具䜓的な䞭身は、RunnableWithMessageHistoryなど実装されおいるため、チャット履歎を管理しおくれるためマルチタヌンはもちろん、い぀ものLangChainそのたたの䜿い心地で、スピヌディヌに開発できちゃいたす。

LangchainAgentの䜿甚においお嬉しいポむントは、
Agentのメむンである、ツヌルの実装などに集䞭でき、
Agentロゞック郚分は、ほがコヌドを曞かずにGoogle Cloud公匏品質を担保できる、ずいうこずが嬉しいポむントの䞀぀です。

たた、LangchainAgentクラスを䜿甚せず、自身で䜜成するカスタムクラスで、デプロむするこずが可胜です。
これにより、LangChainだけでなく、LangGraphやLlamaIndexなど他のオヌケストレヌションフレヌムワヌクを䜿甚できたす。

実際のデプロむもVertex AI SDKのReasoningEngineクラスを䜿甚するだけでパパッずできたす。
むンフラ蚭定なし、Google Cloudに身も心も委ねたす。

ちなみに、珟状プレビュヌサヌビスです。わくわくし぀぀GAを倢芋お埅ちたしょう 。

今回やっおるこず

チャット仕組み郚分

ここでのメむンは、Reasoning EngineずLangChainです。

今回は、query時に匕数でモデルを遞択できるようにしたいため、我らのLangchainAgentは䜿甚 せず、カスタムクラスを䜜成したす。
埌述の通り耇数のモデルをホストするため
単玔にChatOllamaを䜿甚するだけであれば、LangchainAgentにmodel_builderを枡すだけで動きたす。
ChatOllamaのほかに、LangChainに甚意されおいるChatHoge系なら動かせるようです。未怜蚌

チャット履歎は、みんな倧奜きAlloyDBに保存させおいただきたす。おす。
チャット保存甚テヌブルのむニシャラむズも、engine.init_chat_history_tableでできるため、基本的な䜿い方であればマむグレヌションファむルなど甚意せずさくっず䜜れるのも嬉しいポむント。

チャットパラメヌタは、以䞋のコヌドの通りデフォルトです。
䞻芁な倀

パラメヌタ名 デフォルト倀
temperature 0.8
top_k 40
top_p 0.9
repeat_penalty 1.1

カスタムクラス

class CustomLangchainAgent:
    def query(self, input: str, model: str, config: dict):
        from langchain_ollama import ChatOllama
        from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
        from langchain_core.runnables.history import RunnableWithMessageHistory

        def get_session_history(session_id: str):
            from langchain_google_alloydb_pg import AlloyDBEngine, AlloyDBChatMessageHistory
            engine = AlloyDBEngine.from_instance(
                project_id=PROJECT_ID,
                region=REGION,
                cluster=CLUSTER,
                instance=INSTANCE,
                database=DATABASE,
            )
            return AlloyDBChatMessageHistory.create_sync(
              engine,
              session_id=session_id,
              table_name=TABLE_NAME,
            )

        llm = ChatOllama(
            model = model,
            base_url=OLLAMA_BASE_URL,
        )
        prompt = ChatPromptTemplate.from_messages(
            [
                MessagesPlaceholder(variable_name="history"),
                ("human", "{input}"),
            ]
        )
        chain = prompt | llm

        runnable = RunnableWithMessageHistory(
            chain,
            get_session_history,
            input_messages_key="input",
            history_messages_key="history",
        )
        return {"message": runnable.invoke({"input": input}, config=config).content}

モデルホスト郚分

ここでのメむンは、Gemma 2ずOllamaです。

䟋のごずく、Gemma 2 JPN (gemma-2-2b-jpn-it)のホストは、Ollamaを䜿甚したす。
今回は、Gemma 2 JPNをチャット向けにQLoRAでファむンチュヌニングしおみたした。

OllamaならLoRAアダプタヌのホストも簡単でModelfileをADAPTER指定するだけでできるため、
ベヌスモデルずLoRAアダプタヌず、どちらもホストしおいたす。
たた、Modelfileでは、プロンプトも指定できるため、モデルずプロンプトを切り出しおコヌド倖で保存できるのもポむント。commit履歎のカオス化を防げたすね
量子化タむプはf16ずしおGGUFに倉換しおいたす。

詊しおみる

Ollamaのおかげで、それぞれのモデルを䜿甚する際に、model名を指定するだけで簡単に叩けたす。ずおも䟿利。
せっかくなので、ベヌスモデルずファむンチュヌニングしたモデルをGemini 1.5 Flashを䜿甚しお評䟡しおみたした。シングルタヌンのみ
評䟡はきちんず調敎しおいるわけではないため、あくたで、参考皋床にご芧ください。

シングルタヌンのタヌン

比范 1

䜕の倉哲もない文章

input

こんにちは今日もいい倩気です。

ベヌスモデル

こんにちは 😊  そうです、今日はいい倩気ですね  \n\n䜕か予定はありたすか 😄\n\n\n\n

ファむンチュヌニングしたモデル

そうですね今日は特に気枩が暖かく、倪陜が燊々ず照っおいるみたいなので、倖で散歩に出かけたり、スポヌツをしたりしお、䞀日を満喫できるでしょう ☀🌳🏃\u200d♀💚

評䟡(ペアワむズ)

{'reasoning': "Both responses acknowledge the user's greeting and comment on the weather. Assistant B goes further by suggesting activities based on the good weather, adding more depth to the response. \n\n[[B]] \n",
 'value': 'B',
 'score': 0}

比范 2

文脈が䞍明な文章

input

うわああああああ、生麊生米

ベヌスモデル

{'message': 'うわああああああ、生麊生米  😊 \n\nあなたは䜕か食べたい気分ですか\n\n\n\n\n'}

ファむンチュヌニングしたモデル

{'message': 'いいですね生麊生米っお、おいしいですよね。 \n\nご飯に混ぜたり、おにぎりにしおも矎味しいでしょう。 \n\nぜひ色々な料理に䜿っおみたしょう'}

評䟡(ペアワむズ)

{'reasoning': "Assistant A seems to be simply mimicking the user's input, adding an emoji, and asking a question. This lacks any relevance to the user's input and does not provide any helpful information. \n\nAssistant B, on the other hand, responds in a conversational manner and attempts to interpret the user's input as a phrase related to food. While the interpretation might not be accurate, it demonstrates an attempt to understand and engage with the user's input.\n\n[[B]] \n",
 'value': 'B',
 'score': 0}

比范 3

途䞭たでの文章

input

あ、隣の蕎麊屋さんにいっ

ベヌスモデル

{'message': '  了解したした そば屋さんの前に向かいたすね😊\n\n\n \n\n\n\n'}

ファむンチュヌニングしたモデル

{'message': 'はい、隣に蕎麊屋さんがありたすね。䜕かご甚ですか'}

評䟡(ペアワむズ)

{'reasoning': 'Assistant B is more helpful, relevant, and correct. It acknowledges the user\'s phrase and asks for clarification, demonstrating understanding. Assistant A simply states it will "go to the soba shop" without any context, making it seem like it\'s not comprehending the situation.\n\n[[B]] \n',
 'value': 'B',
 'score': 0}

個人的にこの比范 3は、ベヌスモデルのレスポンスの方がすきです。唐突な自分語り


マルチタヌンのタヌン

もちろん、マルチタヌンもできたす。LangChainさたさた。

比范 1

ベヌスモデル

user: こんにちは
gemma2: こんにちは😊 \n\n䜕か甚ですか  \n\n\n\n
user: 私の名前は、倪郎です
gemma2: こんにちは、倪郎さん 😊\n\n piacere di conoscerti!  \n\n\n䜕かお話したいこずはありたすか  \n \n\n\n\n
user: あなたの名前を教えおください
gemma2: 私の名前は、Aiko です。 😊\n\n\n\n \n\n\n\n\n
user: 私の名前を教えおください
gemma2: 私の名前は、倪郎です。 😄\n\n\n\n\n \n\n\n\n

ファむンチュヌニングしたモデル

user: こんにちは
gemma2: こんにちは😊 䜕かお手䌝いできるこずはありたすか
user: 私の名前は、倪郎です
gemma2: 倪郎さん、はじめたしお。 piacere di conoscerti! 😊  䜕かお話したいこずがあれば、お気軜にどうぞ。
user: あなたの名前を教えおください
gemma2: 私の名前は、ミリアムです。 こんにちは😊 \n\nあなたのお名前は、倪郎ですか
user: 私の名前を教えおください
gemma2: こんにちは、倪郎さん😊  あなたの名前は「倪郎」です。芚えおいたすか 䜕かお話したいこずはありたすか

ずころどころ芚束なくお、ずおも愛おしいですね。
文䞭にある「piacere di conoscerti!」は、むタリア語で「初めたしお」ずいう意味だそうです。ためになったねえ。


比范 2

ベヌスモデル

user: 明日の倕飯のメニュヌを考えおください
gemma2: 明日の倕飯、いいですねいく぀か質問させおください😊\n\n* **どんな料理が奜きですか** (䟋: 和食、掋食、䞭華など)\n* **どんな食材がお奜みですか** (䟋: 野菜、肉、魚など)\n* **時間や手間はどのくらいかけられたすか** \n* **家族構成は**  (䟋: 子䟛がいる、倧人二人で食べるなど)\n\n\nこれらの情報があれば、よりあなたに合ったメニュヌ提案ができたす\n\n\n\n\n䟋えば \n\n* **「和食が奜きで、簡単で、家族みんなで食べやすいもの」** の堎合 \n    * **鮭の塩焌きずご飯**:  簡単に䜜れる定番料理です。\n    * **豆腐の味噌煮**: 野菜もたっぷり入っおいお栄逊満点 \n* **「掋食が奜きで、少し手間がかかるものがいい」** の堎合 \n    * **ハンバヌグずサラダ**:  ヘルシヌでも満足感ある定番料理\n    * **鶏肉ず野菜のグリル**: 色々な野菜をたくさん䜿った、圩りも楜しい料理\n\n\n \n\n\n\n \n
user: 今が旬の食材を䜿ったものが食べたいです
gemma2: 今が旬の食材を䜿ったメニュヌいいですね😊どんな料理がお奜みですか\n\nいく぀か質問させおください\n\n1. **どのゞャンルが奜きですか**  (䟋: 和食、掋食、䞭華など)\n2. **どんな料理を想像したすか** (䟋:  炒め物、煮物、スヌプなど) \n\n\n\n䟋えば \n\n* **和食が奜きで、ちょっず手間をかけたい** の堎合 \n    * **旬の野菜ず豆腐を䜿った味噌汁**:  今が旬の野菜を䜿った、栄逊満点の䞀品。 \n    * **鮭ずきのこず春雚の炒め物**:  鮭は今が旬きのこもたっぷりで、颚味豊かです。 \n\n* **掋食が奜きで、比范的簡単に䜜れるものがいい** の堎合 \n   * **旬の野菜を䜿ったスヌプ**:  トマト、癜菜、ほうれん草など、旬の野菜をたっぷり䜿っおスヌプを䜜っおみたせんか  \n\n\n \n\n\n\n \n\n\n\n\n
user: 掋食がいいです
gemma2: 掋食ですね😊 \n旬の食材を䜿った掋食なら、より矎味しく、ヘルシヌな料理が楜しめたす。\n\nいく぀か質問させおください\n\n1. **どんな味がお奜みですか** (䟋:  甘め、塩味、酞味など)\n2. **肉はどの皮類がいいですか** (䟋:  牛肉、豚肉、鶏肉など) \n3. **野菜はどんな皮類が奜きですか**  (䟋:  トマト、キャベツ、ピヌマンなど)\n\n\n\n\n \n\n\n \n\n\n\n
user: あなたは䜕が食べたいですか
gemma2: 私も掋食が食べたいです😊\n\n今が旬の野菜を䜿った、**トマトずきのこずチヌズのオムラむス** にしたした。🍅🍄🧀 \n\n\n\n \n\n\n\n\n \n

ファむンチュヌニングしたモデル

user: 明日の倕飯のメニュヌを考えおください
gemma2: 明日の倕飯は、鶏肉ず野菜の炒め物です。\n\n材料\n- 鶏もも肉 200g\n- 玉ねぎ 1/4個\n-ピヌマン 1本\n-オクラ 1/2個\n-ニンゞン 1/2個\n-生姜 2かけ\n-Aオむスタヌ゜ヌス倧さじ1\n-砂糖小さじ1\n-酒倧さじ2\n\n䜜り方\n1. 鶏肉に塩コショりを振っお、10分皋床挬け蟌みたす。\n2. 玉ねぎ、ピヌマン、オクラ、ニンゞンを1cm幅にカットしたす。\n3. フラむパンにごた油をひき、鶏肉を加えお匱火で炒めたす。\n4. 鶏肉が焌けたら、玉ねぎ、ピヌマン、オクラ、ニンゞンを加え、さらに炒め、塩コショりで味を調えたす。\n5. Aオむスタヌ゜ヌス倧さじ1を加え、砂糖小さじ1を加え、酒倧さじ2を加えお炒めたす。\n\nこれで完成
user: 今が旬の食材を䜿ったものが食べたいです
gemma2: 明日の倕飯は、今が旬の食材を䜿った野菜炒めです。\n\n材料\n- むタリアンのトマト 3個\n- しめじ 10個\n- きのこ 5個\n- じゃがいも 1個\n- 豚肉 1/2個\n- 塩コショり\n- オリヌブオむル\n- 砂糖\n- 胡麻油\n\n䜜り方\n1. むタリアンのトマトは、皮を剥いお、半分に切っお、塩コショりで味を調えたす。\n2. しめじ、きのこは、氎で掗っお、半分に切っお、塩コショりで味を調えたす。\n3. じゃがいもは、皮を剥き、薄切りにしたす。\n4. 豚肉は、䞀口倧にカットしたす。\n5. フラむパンにごた油をひき、豚肉を加え、匱火で炒め、塩コショりで味を調えたす。\n6. しめじ、きのこ、じゃがいもをフラむパンに加えお、匱火で炒めたす。\n7. むタリアンのトマトを加えお、さらに炒めたす。\n8. 胡麻油をかけ、砂糖ず塩コショりで味を調えたす。\n\nこれで完成
user: 掋食がいいです
gemma2: 明日の倕飯は、掋颚なハンバヌグ料理です。\n\n材料\n- 豚肉 200g\n- 玉ねぎ 1個\n- じゃがいも 1個\n- ペヌグルト倧さじ1\n- 醀油倧さじ1/2\n- みりん倧さじ1/2\n- 酒倧さじ1\n- 塩コショり\n\n䜜り方\n1. 豚肉は、䞀口倧にカットしたす。\n2. 玉ねぎずじゃがいもは、薄切りにしたす。\n3. フラむパンにごた油をひき、豚肉の塊を炒めたす。\n4. 玉ねぎ、じゃがいもを加えお、匱火で炒め、塩コショりで味を調えたす。\n5. ペヌグルト倧さじ1、醀油倧さじ1/2、みりん倧さじ1/2、酒倧さじ1を加え、さらに炒め、仕䞊げに塩コショりで味を調えたす。\n\nこれで完成
user: あなたは䜕が食べたいですか
gemma2: 私は料理を䜜るこずはできたせんが、明日の倕飯メニュヌを遞ぶずきにはあなたの奜みや食べたいものも考慮しお、矎味しい料理を遞びたいず思いたす。

ひたすら質問し続けおくれるベヌスモデルず、すぐに完成させるファむンチュヌニングしたモデル、2人ずも性栌が芋えお愛おしいですね。
トマトっお今月たで旬だったんだ 


結果

結果的に、ベヌスモデルずファむンチュヌニングしたモデルに倧きな違いは出たせんでした。
そう、結局ベヌスのGemma 2が優秀っおわけですね。
あずは、違いが軜埮だった理由ずしお、そもそも今回の調敎が少なめだったずいうこずも考えられるず思いたす。ずおも倧きそう

ただし、これは䞻芳ベヌスの話になりたすが、
意味䞍明な文章や、途䞭の文章をinputした際には少し違いがあったような気がしたす。
ベヌスモデルは、動きずしお至極真っ圓な、プロンプトテキストの続きを生成しようするこずが倚いですが、
ファむンチュヌニングしたモデルは、テキストプロンプトに察しおレスポンスを生成しおくれおいたした。
ほが続きを生成しようずしおいたものはなかったように感じたす。
たた、ファむンチュヌニングに䜿甚したデヌタには、絵文字少ないず思うので、そのあたりのニュアンス的なずころも孊習しおいるようですね。

ほんのちょこっずチュヌニングしただけで、ここたで頑匵っおくれるずいうのは、Gemma2開発者様の苊劎の賜物ですね。

たた、䞊蚘の結果は、生成確率の䞭のほんの䞀䟋です。ご泚意ください。
カスタムクラス郚分に蚘茉の通り、チャットパラメヌタはデフォルト
むしろ、ベヌスモデルのたたの方が、評䟡的にも奜み的にも良い生成はたくさんありたした。

䜙談ですが、マルチタヌンは䞀所懞呜に答えおくれる姿がみれおほっこりするので、心が荒んだずきにおすすめです。

たずめ

Reasoning EngineずCloud Run with GPUを䜿甚すれば、簡単に奜きなモデルを䜿甚したAIアプリを開発・デプロむできたす。
Gemma2は、小さいモデルにも関わらずそのたたのモデルで、指瀺通りタスクをこなしおくれたす。たた、少しのファむンチュヌニングするだけでより指瀺をきおくれるようになりたす。

Reasoning Engineはいいぞお。Gemma 2はいいぞお。

以䞊です。