James Tsang

James Tsang

A developer.
github
twitter
tg_channel

ARTS 打卡第 4 日

今日は 20 分遅れて打刻しました。残業と弟と長話をしたため、その後 LLM を使った TDD 開発に関する記事を選んで読んだのですが、内容が長すぎて、その日の打刻を実現するために別の記事に変更しましたが、結局は時間オーバーになってしまい、しかも質の低い記事に変更してしまったので、得られたものは少なかったです。とにかく、この記事で打刻を完了し、LLM を使った TDD の記事を次の打刻記事の内容にします。

A:263. 丑数#

丑数とは、質因数が 2、3、5 のみで構成される正の整数です。
整数 n が与えられたとき、n が丑数であるかどうかを判断してください。もしそうであれば、true を返し、そうでなければ false を返します。
例 1:
入力:n = 6
出力:true
説明:6 = 2 × 3
例 2:
入力:n = 1
出力:true
説明:1 には質因数がないため、その全ての質因数は {2, 3, 5} の空集合と見なされます。通常、これを最初の丑数と見なします。
例 3:
入力:n = 14
出力:false
説明:14 は丑数ではありません。なぜなら、別の質因数 7 を含んでいるからです。

比較的簡単な問題で、特に理論的な方法を考えつかなかったので、最初は 0 が丑数ではないことを見落としていましたが、修正した後に提出しました:

function isUgly(n: number): boolean {
  if (n === 0) {
    return false
  }
  if (n === 1) {
    return true
  }
  if (n % 2 === 0) {
    return isUgly(n / 2)
  }
  if (n % 3 === 0) {
    return isUgly(n / 3)
  }
  if (n % 5 === 0) {
    return isUgly(n / 5)
  }
  return false
}

提出結果は:

1013/1013 cases passed (56 ms)
Your runtime beats 100 % of typescript submissions
Your memory usage beats 38.09 % of typescript submissions (44 MB)

ここで注意すべきは、私は再帰を使って実装したということです。while (true)のループに変更することも可能です。

R:LangChain + Streamlit + Llama: Bringing Conversational AI to Your Local Machine#

皆さんは大言語モデルや LangChain に非常に慣れていると思うので、ここでは簡単に説明します。

大言語モデルは大きな注目を集めており、多くの開発者が大言語モデルを使ってチャットボット、個人アシスタント、またはコンテンツ生成を行っています。大言語モデルの可能性は、開発者、AI、NLP コミュニティにおいて大きな熱意を生み出しています。

特定の分野のデータを大言語モデルに注入することで、特に社内の文書知識ベースにおいて、効率的にクエリ問題を解決することができます。この目的のためのアーキテクチャは「検索強化生成」または「生成的質問応答」と呼ばれます。

LangChain とは何ですか?LangChain は、大言語 AI アプリケーションの構成要素を便利に連携させるための開発フレームワークで、開発者がチャットボットなどのアプリケーションを迅速に実現できるようにします。

この記事では、LangChain と LLaMA 7B モデルを使用して文書アシスタントを作成する方法について説明します (個人的には少し古くなったと感じています。今は LLaMA2 です)

記事の情報構造:

  1. 仮想環境とファイル構造の作成
  2. ローカルで大言語モデルを取得
  3. 大言語モデルを LangChain に統合し、Prompt テンプレートをカスタマイズ
  4. 文書検索と回答生成
  5. Streamlit を使用してアプリを作成

1. 仮想環境とファイル構造の作成#

基本的なファイル構造と Python 仮想環境を作成します。主にモデルファイル、Notebook ファイル、app.py アプリケーションエントリファイルが含まれます。著者のリポジトリをクローンできます:DocQA

2. ローカルで大言語モデルを取得#

LLaMA は Meta がリリースした大言語モデルで、LLaMA2 は無料で商用利用できます。この記事では LLaMA1 を使用しています。HuggingFaceで LLaMA モデルを見つけて、bin ファイルを models ディレクトリにダウンロードしてください。

GGML はオープンソースの C++ で書かれた機械学習テンソルライブラリで、消費者向けハードウェア上で LLM を量子化して実行できます。

では、量子化とは何でしょうか?LLM の重みは浮動小数点数であり、整数値よりもスペースと計算能力を多く占有します。量子化は、リソースの占有を減らすために重みの精度を減少させることです。GGML は 4 ビット、5 ビット、8 ビットの量子化をサポートしています。

メモリ、ハードディスク、およびモデルの効果を考慮して、モデルパラメータのサイズと量子化方式を選択する必要があります。サイズが大きく、量子化精度が高いほど効果が良くなりますが、リソースの占有も増えます。

GGML が C++ ライブラリであれば、Python でどのように使用するのでしょうか?これには llama-cpp-python プロジェクトが必要です。これは llama.cpp の Python バインディングで、Python を使用して LLaMA モデルを実行できます。

これだけの説明をしましたが、実際には非常に簡単に実行でき、数行の Python コードで済みます:

image

3. 大言語モデルを LangChain に統合し、Prompt テンプレートをカスタマイズ#

LLM にとって、実行を簡略化して理解することは、テキストを入力し、テキストを出力することです。したがって、LangChain にとっても大部分の作業はテキスト中心です。

Prompt の微妙な違いが LLM の実行結果に大きな差を生むため、質の高い Prompt を生成する方法を考慮するために Prompt Engineering の概念が特別に生まれました。LLM とのシームレスなインタラクションのために、LangChain は Prompt テンプレート開発機能を提供しており、通常はテキストテンプレートと動的パラメータの 2 つの部分で構成されます。

簡単なアプリケーションでは、Prompt と入力パラメータを LLM に渡して結果を生成するだけで済みますが、複雑なアプリケーションでは一般的に LLM と他のコンポーネントを接続する必要があります。LangChain は接続の開発方法を提供しており、一連のコンポーネントを直列に呼び出すことができます。

4. 文書検索と回答生成#

多くの LLM アプリケーションでは、ユーザーが必要とするデータはモデルのトレーニングデータセットには含まれておらず、Prompt に外部から追加する必要があります。LangChain は、これらのデータをロード、変換、保存、クエリするために必要なコンポーネントを提供しています:

image

この 5 つのプロセスは、文書のロード - 文書の変換 - 埋め込み - ベクトルストレージ - ベクトル検索です。以下は文書検索の全プロセスです:

image

このプロセスは比較的長いため、ここでは詳しく説明しませんが、これはローカルデプロイのソリューションであるため、埋め込みモデルもリモートサービスを使用せず、LLaMA モデルを使用して埋め込みを行う LangChain コンポーネントである LlamaCppEmbeddings を使用しています。

5. Streamlit を使用してアプリを作成#

著者は Streamlit について詳しく説明していませんが、これは主な流れにとって比較的オプションのステップです。ただし、Streamlit を使用してファイルをアップロードする際、著者はメモリ不足を防ぐために、アップロードされたファイルを一時ディレクトリに raw.txt として保存することを強調しています。現在は txt タイプのファイルのみがサポートされていますが、PDF や CSV ファイルをサポートするように変更することもできます。最後に Streamlit ライブラリを呼び出すことで、この LangChain ベースの LLM アプリケーションをウェブアプリに変えることができました:

# Bring in deps
import streamlit as st 
from langchain.llms import LlamaCpp
from langchain.embeddings import LlamaCppEmbeddings
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma


# Customize the layout
st.set_page_config(page_title="DOCAI", page_icon="🤖", layout="wide", )     
st.markdown(f"""
            <style>
            .stApp {{background-image: url("https://images.unsplash.com/photo-1509537257950-20f875b03669?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1469&q=80"); 
                     background-attachment: fixed;
                     background-size: cover}}
         </style>
         """, unsafe_allow_html=True)

# function for writing uploaded file in temp
def write_text_file(content, file_path):
    try:
        with open(file_path, 'w') as file:
            file.write(content)
        return True
    except Exception as e:
        print(f"Error occurred while writing the file: {e}")
        return False

# set prompt template
prompt_template = """Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.
{context}
Question: {question}
Answer:"""
prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"])

# initialize hte LLM & Embeddings
llm = LlamaCpp(model_path="./models/llama-7b.ggmlv3.q4_0.bin")
embeddings = LlamaCppEmbeddings(model_path="models/llama-7b.ggmlv3.q4_0.bin")
llm_chain = LLMChain(llm=llm, prompt=prompt)

st.title("📄 Document Conversation 🤖")
uploaded_file = st.file_uploader("Upload an article", type="txt")

if uploaded_file is not None:
    content = uploaded_file.read().decode('utf-8')
    # st.write(content)
    file_path = "temp/file.txt"
    write_text_file(content, file_path)   
    
    loader = TextLoader(file_path)
    docs = loader.load()    
    text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
    texts = text_splitter.split_documents(docs)
    db = Chroma.from_documents(texts, embeddings)    
    st.success("File Loaded Successfully!!")
    
    # Query through LLM    
    question = st.text_input("Ask something from the file", placeholder="Find something similar to: ....this.... in the text?", disabled=not uploaded_file,)    
    if question:
        similar_doc = db.similarity_search(question, k=1)
        context = similar_doc[0].page_content
        query_llm = LLMChain(llm=llm, prompt=prompt)
        response = query_llm.run({"context": context, "question": question})        
        st.write(response)

image

私は個人的に Streamlit のアプリケーションに関心があり、Gradio でプロトタイプ開発を実現した後、より複雑なアプリケーション開発には Streamlit の機会があると思っています。しかし、この記事では深く掘り下げられておらず、私が最も見たかった内容があっさりと略されていました。

T:CoDeF#

ビデオからビデオへの LLM で、出力が安定しており、品質も良好です。

image

S:SQ3R 読書法#

SQ3R は 5 つの単語を表します:Survey(調査)、Question(質問)、Read(読む)、Recite(再述)、Review(復習) 学習する前に、まず内容をざっと見て、その後この調査に基づいて自分の質問を提起します。これは何についてのもので、どのような問題を解決するのか。そして、その質問を持って深く読み進めます。読みながら答えを見つけ出します。
最後に本を閉じて、自分で一度再述します。この本は何についてのもので、私たちはどのような問題を持っていて、この本はどのように解決しているのか。最後に復習を行い、学習成果を強化します。この 5 つのステップを経て、この本の内容は本当に吸収されることができます。


Reference:

  1. ARTS 打刻活動
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。