大福餅

大福餅

Langchain を触ってみる

www.udemy.com

 

LangChain を触っている。学習途中ではあるが、簡単にメモ。

 

概要

  • 講義元では「gpt-3.5-turbo」を使っているが、それ以外のモデルでも使うことは可能
    • 但し記述を少し変えなくてはならない
    • 例えばhuggingfaceのモデルではhuggingface 用のライブラリを用いる
    • from langchain.llms import HuggingFacePipeline
      from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
      import torch

      # GPUの確認
      device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
       
      model_id = "google/gemma-7b-it"
      tokenizer = AutoTokenizer.from_pretrained(model_id)
      model = AutoModelForCausalLM.from_pretrained(model_id).to(device)
      pipe = pipeline(
          "text-generation",
          model = model,
          tokenizer = tokenizer,
          max_new_tokens = 512,
      )
      llm = HuggingFacePipeline(pipeline=pipe)

       

  • プロンプトのテンプレートを作っておき、ユーザーの入力部分を変数にしておく
    • template = '''
      <bos><start_of_turn>user
      次のコマンドの概要を説明してください。
      コマンド:{command}
      <end_of_turn><start_of_turn>model
      '''

       commandがそれにあたる。

  • 最新のバージョンでは、LCEL」(LangChain Expression Language) という記述でプロンプトとモデルを結びつける。
    • qa_chain = (
          {'command': RunnablePassthrough()}
          | PromptTemplate.from_template(template)
          | llm
          | StrOutputParser()
      )
    • 1行目:入力部分 (commandにユーザーが入力したテキストが代入される)
    • 2行目:テンプレート (先程作ったもの)
    • 3行目:モデル (llm = HuggingFacePipeline(pipeline=pipe))
    • 4行目:恐らく出力
  • .invoke()で入力
  • プロンプトを繋げたい場合は、以下のように記述する。

    • cot_summarize_chain = (
          {'question': RunnablePassthrough()}
          | PromptTemplate.from_template(cot_template)
          | llm
          | {'input': StrOutputParser()} # 1つ目のプロンプトの出力を代入
          | PromptTemplate.from_template(summarize_template)
          | llm
          | StrOutputParser()
      )

       

    • 1つ目のプロンプトの出力 (StrOutputParser() ) を2つ目のプロンプトの入力に入れる。
    • このようにしてプロンプトを繋げていくことができる
    • 1つ目のプロンプトの出力を、2つ目のプロンプトで要約させる、といった使い方がある
  • vectorDB を作る際にも、プラットフォームに合わせて関数を変えなくてはならない
    • 講義ではOpenAI embedding を使っていた 
    • 多分、APIを使えるのならばこれが簡単だし知見もたくさんある
    • 自分はFAISS (Facebook のembedding)を用いた
    • from langchain.document_loaders import DirectoryLoader
      from langchain.indexes import VectorstoreIndexCreator
      from langchain_community.vectorstores.faiss import FAISS
      from langchain.embeddings import HuggingFaceEmbeddings
      from langchain.text_splitter import RecursiveCharacterTextSplitter

      loader = DirectoryLoader("./langchain/docs", glob="**/*.md")
      docs = loader.load()

      # チャンクの分割
      text_splitter = RecursiveCharacterTextSplitter(
          chunk_size=100,  # チャンクの最大文字数
          chunk_overlap=10,  # オーバーラップの最大文字数
      )

      vectorstore = FAISS.from_documents(
          docs,
          embedding=HuggingFaceEmbeddings(
              model_name='intfloat/multilingual-e5-base'
          )
      )

       

  • ドキュメントとモデルを結びつけるのも1行で可能
    • qa_chain = (
          {'context': vectorstore.as_retriever(search_kwargs={'k': 3}), 'question': RunnablePassthrough()}
          | PromptTemplate.from_template(template)
          | llm
          | StrOutputParser()
      )

       1行目:vectorstore.as_retrieverを追加

      • search_kwargsはよく分かってない (パラメータ用の設定?多分 'k' はtop_k?)
      • zenn.dev

  • チャットボットのように会話するためには、ConversationChainで良いらしい
    • import langchain
      from langchain.chains import LLMChain
      from langchain.prompts import PromptTemplate
      from langchain.schema.runnable import RunnablePassthrough
      from langchain.schema import StrOutputParser
      from langchain.chains import ConversationChain
      from langchain.memory import ConversationBufferMemory

      template = '''
      <bos><start_of_turn>user
      以下は、人間とAIが会話している様子です。AIは会話内容を考慮し、人間の質問に対して回答してください。AIは質問に対する答えを知らない場合は「知らない」と答えてください。
      会話内容:
      人間: {input}
      AI:
      <end_of_turn><start_of_turn>model
      '''
      prompt = PromptTemplate(
          input_variables=['history', 'input'],
          template=template
      )

      conversation = ConversationChain(llm = llm,prompt=prompt, memory=ConversationBufferMemory())

      while True:
        user_message = input("You: ")
        ai_message = conversation.predict(input=user_message)
        print(f"AI:{ai_message}")

       

所感

  • 講義元がgptモデルを使っていたので、huggingface用に変えるのが大変だったが、分かれば数行で設定できるを実感した
  • 所謂RAGの設定も、複雑ではなく、数行のコードを実行すればモデルがドキュメントを基にした回答をしてくれることを確認した
    • 個人的にもう少し難しいものだと思っていたから、実際に触って容易だったので、驚いた
    • 利用用途も多いので、これは基本的な知識として覚えておきたい
  • LangChainは現在もバージョンアップが頻繁に起きているため、記法などが頻繁に変わっているようである
    • GPTモデル使えるなら、講義元と同様のバージョンを使うのが無難
    • ただLCELはデフォルトスタンダードになっていく可能性があるようで、ここはあえて最近のバージョンをつかって書いて学習するというのもアリだと思う
  • 講義の目的は、Webアプリケーションに組み込む、またSlackのチャットボットを作るの2つ
    • なので、ここから形にしていくのが楽しみである。
    • 分かりやすく説明してくださっているので、やってて楽しい