自分のハードウェアでのコード理解
'Understanding code on your own hardware'
LangChainとローカルハードウェアを使用して、コードについて話すLLMのセットアップ
現在、大規模言語モデル(LLM)が実行できるさまざまなタスクの中で、ソースコードの理解は、ソフトウェア開発者やデータサイエンティストとしてソースコードと取り組んでいる場合に特に興味深いかもしれません。コードに関する質問をすることができるチャットボットを持つことは素晴らしいことではないでしょうか?データの前処理はどこに実装されていますか?ユーザーの認証を検証するための関数はすでに存在しますか?calculate_vector_dim関数とcalculate_vector_dimension関数の違いは何ですか?正しいファイルを自分で検索する代わりに、ボットに質問をして、回答と関連するコード断片が含まれているファイルへのポインタを受け取ることができます。このメカニズムはセマンティックサーチと呼ばれ、その有用性を想像できるでしょう。
このチュートリアルでは、まさにそれを行うLangChainボットの実装方法を紹介します。さらに、コードを手渡しで提供しないという具体的なデータプライバシーの問題に焦点を当てます。作成したコードは私有財産であり、機密情報や貴重な知識を含んでいる可能性があります。他社がホストするLLMに送信することを望まないかもしれませんし、会社のポリシーによっては外国にあるかもしれない他社のLLMに送信することが許可されないかもしれません。そのため、このチュートリアルでは、ローカルハードウェア上で実行されるコード理解ボットのセットアップ方法を紹介します。つまり、あなたのコードは常にインフラストラクチャから出ることはありません。
さあ、早速始めましょう!まず、セマンティックサーチの一般的なプロセスの簡単な紹介を行います。その後、コード理解のためのボットを実装します。
セマンティックサーチの紹介
まず、セマンティックサーチの一般的なアイデアを簡単に説明します。このアプローチは、リトリーバルとLLM自体による回答生成という2つの主要なステップで構成されています。リトリーバルのステップでは、関連情報を含むドキュメントが選択され、それらがLLMにフィードされて自然言語の回答が生成されます。たとえば、transform_vectorsという関数についての質問をする場合、リトリーバルはその質問に答えるために関連するファイルを選択します。それには、transform_vectors関数が実装されているファイルだけでなく、それを使用しているファイルやそれに言及しているドキュメントの一部も含まれる場合があります。第2ステップでは、それらのファイルの内容が次のようなプロンプトでLLMに与えられます:
"""以下の文脈を考慮して質問に答えてください。 <document 1><document 2>...<document n>質問: <ユーザーの質問>回答:"""
LLMは、与えられたドキュメントの情報を使用して、質問に対する自然言語の回答を作成します。
それがセマンティックサーチの主なアイデアです。さあ、実装を始めましょう!まず、必要なライブラリをインストールし、データを読み込む必要があります。
必要なライブラリのインストール
開始する前に、Pythonが実行される環境をセットアップし、次のパッケージをインストールしていることを確認してください:
pip install langchain==0.0.191pip install transformers
ドキュメントの読み込み
次に、データを読み込んでLangChainが使用できる形式に変換する必要があります。このデモでは、LangChain自体のコードをダウンロードしますが、もちろん独自のコードベースを使用することもできます:
import osfolder_name = "sample_code"os.system(f"git clone https://github.com/hwchase17/langchain {folder_name}")
すべてのファイルを読み込み、それぞれを1つのファイルに変換します。つまり、各Documentにはコードベースの1つのファイルが含まれます。
from langchain.docstore.document import Document
documents = []
for root, dirs, files in os.walk(folder_name):
for file in files:
try:
with open(os.path.join(root, file), "r", encoding="utf-8") as o:
code = o.readlines()
d = Document(page_content="\n".join(code), metadata={"source": os.path.join(root, file)})
documents.append(d)
except UnicodeDecodeError:
# いくつかのファイルはutf-8でエンコードされていません。今のところ無視します。
pass
検索
Documentsを作成したので、これを検索可能にするためにインデックス化する必要があります。ドキュメントをインデックス化するとは、ドキュメントの最も関連性の高い情報を捉える数値ベクトルを計算することを意味します。プレーンテキスト自体とは異なり、数値のベクトルは数値計算を実行するために使用できます。これにより、類似性を簡単に計算することができ、それを使用して、特定の質問に回答するために関連するドキュメントを決定することができます。
技術的なレベルで、このインデックスは埋め込みを使用して作成し、VectorStoreに保存します。VectorStoreはサービスとして利用できます(例:DeepLake)。これにはいくつかの便利な利点がありますが、このシナリオでは、コードを手放すことは避けたいため、ローカルマシンでVectorStoreを作成します。これを行う最も簡単な方法は、Chromaを使用することです。これにより、メモリ内にVectorStoreが作成され、永続化することができます。
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
hfemb = HuggingFaceEmbeddings(model_name="krlvi/sentence-t5-base-nlpl-code-x-glue")
persist_directory = "db"
db = Chroma.from_documents(documents, hfemb, persist_directory=persist_directory)
db.persist()
from_documents関数内で、インデックスが計算され、Chromaデータベースに保存されます。次回から、from_documents関数を再度呼び出す代わりに、永続化されたChromaデータベースをロードすることができます:
db = Chroma(persist_directory=persist_directory, embedding_function=hfemb)
上記のように、埋め込みとしてkrlvi/sentence-t5-base-nlpl-code-x-glueを使用しました。これは、オープンソースのGitHubライブラリのコードで訓練された埋め込みです。埋め込みを使用する際には、コードで訓練されていることが重要です。自然言語のみで訓練された埋め込みは、おそらく性能が低くなります。
VectorStoreと埋め込みが準備できたので、Chromaデータベースから直接リトリーバを作成できます:
retriever = db.as_retriever()
LLM
最後に必要なコンポーネントはLLMです。最も簡単な解決策は、ホストされているLLMを使用することです(例:OpenAIインターフェイスを使用)。しかし、私たちはコードをそのようなホストされたサービスに送信したくありません。代わりに、独自のハードウェア上でLLMを実行します。これには、HuggingFacePipelineを使用します。これにより、LangChainフレームワークでHuggingFaceのモデルを使用することができます。
from langchain import HuggingFacePipeline
import transformers
model_id = "mosaicml/mpt-7b-instruct"
config = transformers.AutoConfig.from_pretrained(model_id,trust_remote_code=True)
tokenizer = transformers.AutoTokenizer.from_pretrained(model_id)
model = transformers.AutoModelForCausalLM.from_pretrained(model_id, config=config, trust_remote_code=True)
pipe = transformers.pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=100)
llm = HuggingFacePipeline(pipeline=pipe)
以下の通り、私はモザイクmpt-7bモデルを使用しました。これはGPU上で約16GBのメモリしか必要としません。私はAutoModelForCausalLMを作成し、それをtransformers.pipelineに渡し、最終的にHuggingFacePipelineに変換しています。HuggingFacePipelineはLangChainの通常のLLMオブジェクトと同じインターフェースを実装しています。つまり、例えばOpenAI LLMインターフェースと同じように使用することができます。
マシンに複数のGPUがある場合、使用するGPUを指定する必要があります。この場合、インデックス0のGPUを使用したいと思います:
config.init_device="cuda:0"model.to(device='cuda:0')pipe = transformers.pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=100, device=0)
上記で設定したいくつかの追加パラメータは次のように説明できます:
- trust_remote_code:LangChain外部からのモデルを実行するためには、これをtrueに設定する必要があります。
- max_new_tokens:モデルが回答で生成することができるトークンの最大数を定義します。この値が低すぎる場合、モデルの応答は質問に回答する前に切り捨てられる可能性があります。
すべてを結びつける
今、必要なすべてのコンポーネントを持っており、それらをConversationalRetrievalChainで組み合わせることができます。
from langchain.chains import ConversationalRetrievalChainqa_chain = ConversationalRetrievalChain.from_llm(llm=llm, retriever=retriever, return_source_documents=True)
最終的に、チェーンにクエリを投げて質問に答えることができます。結果オブジェクトには、自然言語の回答とその回答に到達するために参照されたソースドキュメントのリストが含まれています。
result = qa_chain({"question":"KNNRetrieverのcreate_index関数の戻り値の型は何ですか?", "chat_history":[]})print(f"回答: {result['answer']}")print(f"ソース: {[x.metadata['source'] for x in result['source_documents']]}")
以下は回答です:
回答: KNNRetrieverのcreate_index関数の戻り値の型はnp.ndarrayです。ソース: ['sample_code/langchain/retrievers/knn.py', 'sample_code/langchain/vectorstores/elastic_vector_search.py', 'sample_code/langchain/vectorstores/elastic_vector_search.py', 'sample_code/langchain/vectorstores/opensearch_vector_search.py']
サマリー
以上です!まあ、ある程度ですが。上記のコードで、ソースコードに関する質問をすることができるようになりました。ただし、次のように必要に応じていくつかのステップを変更することがあります。
- LangChainのコードではなく、独自のソースコードをドキュメントとして使用します。
- 異なる埋め込みを試してみてください。埋め込みが適さない場合、リトリーバは適切なドキュメントを見つけることができず、最終的には正確な回答ができません。
- 異なるモデルを試してみてください。より大きくパワフルなモデルが存在しますが、一部はハードウェア上で実行するには大きすぎる場合があります。性能がまずまずで、モデルを満足のいく方法で実行できる最適なポイントを見つける必要があります。
- リトリーバステップを容易にするために、ドキュメントの前処理の異なる方法を試してみてください。一般的な例として、等しい長さのチャンクに分割することが挙げられます。
より良いパフォーマンスを得るために試すべきことはまだまだあります。自由に試して、ボットを自分のニーズに適応させてください。
さらなる読み物
LangChainによるコード理解のさらなる例については、こちらのドキュメントをご覧ください:
- https://python.langchain.com/docs/use_cases/code/
HuggingFaceでは、LangChainで簡単に使用できるモデルや埋め込みを見つけることができます:
- https://huggingface.co/models
この記事がお気に入りでしたか? 私の将来の投稿の通知を受けるためにフォローしてください。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles