生成AI | 株式会社Altus-Five / 株式会社Altus-Five は、技術力で勝負するシステム開発会社です。 Fri, 30 May 2025 09:30:54 +0000 ja hourly 1 https://wordpress.org/?v=6.8.2 /wp-content/uploads/2025/01/cropped-favicon-32x32.png 生成AI | 株式会社Altus-Five / 32 32 js 版の LangChain で LCEL を試す /blog/2024/01/29/js-langchain-lcel-implementation/ Mon, 29 Jan 2024 10:40:00 +0000 http://43.207.2.176/?p=30 最近、私たちのチームは ChatGPT を活用する PoC (Proof of Concept) 案件を受注し、数名で開発に取り組みました。 このプロジェクトでは、主に Python で LangChain、LlamaI […]

The post js 版の LangChain で LCEL を試す first appeared on 株式会社Altus-Five.

]]>
最近、私たちのチームは ChatGPT を活用する PoC (Proof of Concept) 案件を受注し、数名で開発に取り組みました。

このプロジェクトでは、主に Python で LangChain、LlamaIndex、Ragas などを活用して開発検証を行っています。 今、LLM を使った開発は、このあたりのライブラリを使うのが主流であろうと思います。

私の役割は、調査のシナリオ立案と結果のレポート作成だったので、コードを書く機会は無く、 そのため、LLM 関連のプログラムを書くときの大変さとか難易度を肌感覚で掴めておらず、 やや、もどかしさを感じていたので、サンデープログラミングで実装の体験をすることにしました。

業務では、Python 版の LangChain を使用していましたが、日曜大工では、JavaScript版の LangChain を試してみることにしました。 さらに、LangChain は昨年あたりから LCEL という機能を推進しているので、これも試します。

PoC 案件と同じものを作っても面白くないので、私の手習いの実装テーマは「MD の英文テキストを日本語に翻訳する cli ツール」とします。そして、LangChain のマニュアルが、まだ日本語訳がないので、これを翻訳します。

LangChain のドキュメントは、コードのリポジトリの中に一緒にコミットされていて、主に MD と Jupyterノートブックで書かれています。 それらを、Docusaurus というドキュメントシステムで公開するようになっています。 手習いのゴールは、この英文のドキュメントを日本語訳して、Docusaurus でビルドして、日本語でドキュメントシステムが表示されるところまでとします。

Markdown パーサー

ChatGPT に MD のテキストを丸々投げると、max_token を超えることが懸念されるので、分割して翻訳します。 単純に文字数で chunk 分割すると、翻訳結果がおかしくなるので、文単位で分割するのは必須要件となります。 このために、MD ファイルを抽象構文木(AST)に変換し、文の正確な抽出を行います。 この変換には、 remark を使いました。

実際、MD を AST に変換してみると、どのドキュメントも、適度に空行が入っているので、AST の 1 つのテキストノードの中に、 max_token を超えるほどの長い文は、ほとんどありませんでした。 また、コードのブロックもノードタイプで識別できるので、翻訳対象から除外できます。 テストした中では、唯一、MDのテーブルが、テーブル全体で1つのテキストになるので、これだけは、改行を区切り文字として、分割する必要がありました。

翻訳処理

本記事の主題です。 LangChain を使って、 LCEL (LangChain Expression Language)で翻訳処理を実装します。

その前に、翻訳処理の仕様を簡単に説明すると、最初のプロンプトで英文から日本語に翻訳して、その結果を受けて、その翻訳が正しいかを、添削するプロンプトを実行します。添削結果には、翻訳の正確さを数値で出力するように指示して、その数値が閾値を超えるまで、添削を繰り返します。

最初の英文から日本語への翻訳 Chain

const etojPrompt = await DEFAULT_ETOJ_PROMPT;
const etojOutput = (await etojPrompt
  .pipe(model)
  .pipe(new JsonOutputParser())
  .withRetry({ stopAfterAttempt: MAX_LLM_RETRY_ATTEMPTS })
  .invoke(etojInput)) as EtojOutput;

この手習いをやり始めたときには、LCELじゃなくて、従来方式で実装していたのですが、 翻訳されたマニュアルを読んでいるうちに、LCEL で実装することが推奨されていることを知ったので、 せっかくなので、 LCEL での実装に切り替えてみました。 やってることは変わらないのだけど、コードの見通しがよくなったような気がします。

Python で実装すると、たぶん、こんな感じだと思います。

model = ChatOpenAI()
etojPrompt = ChatPromptTemplate.from_template(DEFAULT_ETOJ_PROMPT)
chain = etojPrompt | model | JsonOutputParser()
etojOutput = chain.invoke(etojInput)

| か pipe() かの違いはあるけど、機能的には同じです。

余談ですが、プロンプトの実装で、Python 版では、jinja2 のテンプレートエンジンを使えるんですが、 js 版では、テンプレートエンジンが使えません。 プロンプトの文字列をリアクティブに変数展開したいことがあるので ejs でもよいのでテンプレートエンジンを使えるようにしてほしいです。 今回の実装では、添削を何回か繰り返すときに、前に添削した内容と同じ添削結果を返してくることがあったので、 過去の添削結果を、添削用プロンプトの中に含めて、同じ添削結果を返さないように指示するのですが、 その処理の実装をしているときに、python だったら jinja2 が使えるのにな・・・と思いました。

添削 Chain

最初のチェーンと添削チェーンも、1つの LCEL でつなげた実装にしようかとも思ったのだけど、 正確さが閾値を超えたら終了する仕様を実装するには、カスタムチェーンを作る必要がありそうなので、 そこまではやらずに、チェーンを分けて、ループさせることにしました。

const proofreadChain = proofreadPrompt
  .pipe(model)
  .pipe(new JsonOutputParser())
  .withRetry({ stopAfterAttempt: MAX_LLM_RETRY_ATTEMPTS });

const proofreadInput: ProofreadInput = {
  ...etojInput,
  ...etojOutput,
  histories: [
    { proofreadText: etojOutput.ja, correctness: 0.0, error: '' },
  ],
};
let answer = '';
for (let i = 0; i < MAX_PROOFREAD_ATTEMPTS; i++) {
  const proofreadOutput = (await proofreadChain
    .invoke(proofreadInput)) as ProofreadOutput;
  answer = proofreadOutput.proofreadText;
  if (proofreadOutput.correctness >= TRANSLATION_CORRECTNESS_THRESHOLD) {
    break;
  }
  proofreadInput.histories.push(proofreadOutput);
}
return answer;

LCEL の batch で、効率の良い並列処理を実行するには、カスタムな添削チェーンで、1本につなげた方がよいです。

まとめ

手習いのゴールとした LangChain のマニュアルを日本語訳してドキュメントシステムをローカルで動かすのは、うまく行きました。 LangChain のドキュメントシステムは、amazon linux 2 で実行するようになっていて、ビルドも、それ用になっているので、 開発環境とした ubuntu の devcontainer でビルドできるようにするのに、ひと手間必要でした。

さて、LCEL についてですが、慣れるまで、少し時間がかかりました。 もう少し “らしさ” を出せるかな・・・と思っていたのだけど、 LCEL にするために知恵を絞らないといけないのが、やや面倒だなと感じましたが、おそらく、その知恵を絞ることで、コードが改善されて可読性が上がるのかもしれないです。 でも、LCEL だろうが、LCEL じゃなかろうが、やってることは変わらないので、コスト見合いで、コダワリ過ぎには注意した方がよいかもしれません。

それから、反省点というか注意点ですが、実行時間と、APIの使用料が想定外にかかりました。 LangChain のマニュアルは、1000 ドキュメントくらいあって、何度か止まって再起動していて、 実行するだけで、トータルで 3 日以上かかり、API の利用料が、$500 ちょっとでした。 1ドキュメントを翻訳するのに $0.5 です。

$0.5 が高いか安いかは、人によると思いますが、私の場合、日本語の技術情報が少ない開発をするときに、 英語のマニュアルを、クラウドソーシングなどで翻訳してもらって、 日本語でザックリと読んで概略を掴んでから開発に入ることがあるのですが、 クラウドソーシングに比べると、全然、安いので、個人の財布で実行しようとは思いませんが、 今回作成した翻訳ツールは、実際に使っていこうと思います。

WEB で参照できる英文のマニュアルなら、Google 翻訳で、無料で翻訳することができますが、 日本語で検索しても、ヒットしないので、あらかじめ日本語訳しておくことは、有用だと思います。

少し面白そうな使い道としては、翻訳した MD ファイルを独自に追記編集するとかも有りだと思います。 開発を始めたばかりのときに読んだマニュアルは、まだ、十分に理解できないことがありますが、 開発が進んで、実際に動作を確認していくと、マニュアルに記載されている内容が、理解できたりします。 このときに、おらがチームのマニュアルに、理解の手助けになるようなメモを追加するとか、 実プロジェクトのコード片を追記したりして、独自にドキュメントを育てていくと、Google翻訳よりも、価値があるように思います。

実装した翻訳ツールは、こちらで公開しています。使ってみたい方は、APIの費用に注意して、ご利用なさってください。

https://github.com/minr-dev/md-translation-gpt

最後に、このツールを追加改良したいことを書いておきます。

改良点

  • 過去の翻訳結果をコンテキストとして加えてプロンプトを作成する翻訳した結果を RAG にして refine 法でプロンプトを作成すると、一貫性のある翻訳ができるようになるのではないかと思います。
  • 並列化バッチ処理なので、 LCEL の batch で並列化したいです。実行時間も短縮化できますし。
  • chatbot翻訳されたマニュアルで RAG を駆使して chatbot を動かしたいです。
  • rst の翻訳LlamaIndex のマニュアルも翻訳しようとしたら、こちらは rst (reStructuredText)で書かれていました。 Sphinx です。python の docutils でパースする必要があります。

MIT で公開しているので、有志のご参加をお待ちしています。

The post js 版の LangChain で LCEL を試す first appeared on 株式会社Altus-Five.

]]>
ローカル LLM を動かす /blog/2023/12/22/llm-server-deployment-options/ Fri, 22 Dec 2023 10:40:00 +0000 http://43.207.2.176/?p=29 Google Colab は、GPU が無料で使えるので LLM を動かしてる記事をよく見ます。 特に最近は、 text-generation-webui というツールを使って、コードを書かずに LLM のダウンロードか […]

The post ローカル LLM を動かす first appeared on 株式会社Altus-Five.

]]>
Google Colab は、GPU が無料で使えるので LLM を動かしてる記事をよく見ます。

特に最近は、 text-generation-webui というツールを使って、コードを書かずに LLM のダウンロードから、細かいパラメータ設定なども UI で行って chat を動かす記事が定番の1つのようです。

私も使ってみました。

Google Colab は、使ってないとインスタンスがダウンするので、text-generation-webui の Clob 用のノートブックには、 動かし続けることを目的とした音楽プレーヤーがついていて、それを再生することで、連続使用の状態を維持できるようになってました。 無料枠でそれをするのはモラルに反しないのだろうか?と思いながらも、お試しで、GPUインスタンス(T4 GPU)を選択して、 音楽プレーヤーを再生して連続使用状態にしてみたところ、GPUのインスタンスは、無料枠が短いようで、1日も持たずに、 1カ月分の無料枠を使い果たしました。

有料版は、Colab Pro が月額 1,179 円 で 100 コンピューティングユニットが使えて、Colab Pro+ が月額 5,767 円で 500 ユニットが使えるとなっています。 他にも、Colab Enterprize とかもあります。

コンピューティングユニットの上限を超えると、追加のチャージが必要で、1回のチャージが100ユニット単位です。
T4 GPU は、100ユニット=51時間です。
1日8H、20日稼働で 160H、多少の残業も加えると、毎日の勤務時間中に常時起動しておくような使い方だと、Colab Pro+ が適したプランとなります。
1年だと、5,767 * 12 = 69,204円 です。
なお、100ユニット=51時間 は、T4 GPU の場合で、V100 は 18.5時間、A100 は7.5時間 しか使えません。

T4 と V100 で codellama 13b を使ってみましたが、レスポンス性能は、同じようなものだったので、ひとまず、わざわざ、V100 や A100 を選択する必要はなさそうでした。 ひょっとすると、長いプロンプトを使ったりすると、レスポンス性能に違いが出てくるのかもしれないですが、そこまでは使い込んでいません。

codellama 13b は、オリジナルのモデルは、16G では動かないので、 llama.cpp でGPUのVRAMとCPUを併用するやり方で動かしました。 llama.cpp には、http server の機能もあるので、ひょっとすると、複数人で同時利用もできるのかもしれませんが、これも試していません。

NVIDIA の 16G メモリ以上のグラボの PC を自作すると、4、50万は、かかりそうなので、Colab Pro+ の方がリーズナブルかな・・・。
eGPU という外付け GPU もあるようなので、社内に小さい LLM サーバーが欲しい気もします。
社内に LLM サーバーがあったら、 CodeLlama を動かして、ChatGPT が禁止されているプロジェクトで、使えるようにして、 Open Interpreter などでコード作成を実行してみたい・・・、けど、すでにやってる人たちの記事を読むと、やっぱり GPT-4 じゃないと仕事には使えそうにないです。
だから、社内 LLM サーバーは、まだ早いかな・・・。

と思ってたら、ファインチューニング向けモデル「Mistral 7B Fine-Tune Optimized」が登場、特定タスクにおいてGPT-4を超える性能を発揮という記事を見て、ローカルで LLM を動かしてみたくなってきました。

7B は、ローカル LLM の中でも、一番小さい部類のモデルだけど、それでも、GPT-4 を超えることがあるとしたら、すごく使ってみたいです。

まずは、Google Colab で試してみてから考えようっと。

The post ローカル LLM を動かす first appeared on 株式会社Altus-Five.

]]>
ChatGPT を活用して書いたコードは他人が書いたコードと同じ /blog/2023/09/11/code-from-chatgpt-and-others/ Mon, 11 Sep 2023 10:39:00 +0000 http://43.207.2.176/?p=23 ChatGPT を使って実装したコードを見直してて気づいたのだけど、 自分で考えて書いたコードじゃないので、 なぜこういう実装にしたんだっけ?というのがそもそも無いから、 他の人が書いたコードを読むのと変わらない。 なの […]

The post ChatGPT を活用して書いたコードは他人が書いたコードと同じ first appeared on 株式会社Altus-Five.

]]>
ChatGPT を使って実装したコードを見直してて気づいたのだけど、 自分で考えて書いたコードじゃないので、 なぜこういう実装にしたんだっけ?というのがそもそも無いから、 他の人が書いたコードを読むのと変わらない。

なので、コードリーディングに作業時間がとられる。

対策としては、ChatGPT に対して、「なぜこういう実装にしたのか」コメントとして出力するように指示するのがよい。

単純に”コメントを追加して”とだけ指示すると、1行1行に処理内容のコメントをつけてくるので、それじゃなくて、 「なぜこういう実装にしたのか」説明してもらうのがよさそうです。

The post ChatGPT を活用して書いたコードは他人が書いたコードと同じ first appeared on 株式会社Altus-Five.

]]>
ChatGPT 凄すぎる /blog/2023/01/18/chatgpc-too-awesome/ Wed, 18 Jan 2023 09:19:00 +0000 http://43.207.2.176/?p=188 まだ試してない人は、サインアップして、一回使ってみた方がいい。 ビックリした。 ChatGPT のチャットで、開発中のプログラムコードを転記して、「このクラスのテストコードを書いてほしい」とお願いしたら、 書いてくれちゃ […]

The post ChatGPT 凄すぎる first appeared on 株式会社Altus-Five.

]]>
まだ試してない人は、サインアップして、一回使ってみた方がいい。 ビックリした。

ChatGPT のチャットで、開発中のプログラムコードを転記して、「このクラスのテストコードを書いてほしい」とお願いしたら、 書いてくれちゃった。

残念ながら、回答文が途中で切れちゃったので、そのテストケースが正しいのかは、検証できていないのだけど、 すごく、それっぽいテストコードになってた。

有料会員で登録したら、コードの全文を提示してくれるのかな? あと、試したのは、たとえば、ガントチャートを表示する HTML を作成してほしいとお願いをすると、 サンプルコードを作ってくれて、それに対して、追加の依頼をすると、どんどんプログラムに肉付けしてくれる。

意図したとおりに、動くのかどうかは、わからないけど、これでモブプロできると、最高だな。

ちょうど、ChatGPT の VSCode 拡張もあるようで、似たようなことを支援してくれそうだ。
https://qiita.com/tak001/items/c3000b3ce9b6e72b2ae5

テストケースの作成も、この拡張を使ってやってくれるみたい。

あと、システムの開発って、延々と命名する作業を繰り返してるわけだけど、 機能名、テーブル名、項目名、関数名、クラス名、メソッド名、変数名、テストケース名、・・・・ もう、四六時中、何かに名前をつけまくってる。

この命名を ChatGPT にやってもらうと、いいんじゃないかと思う。 英単語とか、ちょうどよい単語を提示してくれそう。 開発ツールとして、ものすごいポテンシャルがありそうだ。

The post ChatGPT 凄すぎる first appeared on 株式会社Altus-Five.

]]>