ローカルLLMでRAG over Code

ローカルAgentで何をするにせよ、先人の資料やコードを読まないと始まりません。趣味で遊んでる程度の人が、公式ドキュメントを読んだだけでは何にもわからないですからね!

つまり、今、必要なのは!コードの読解を助けてくれるAgentです。
前回のコードにRAG over Codeの能力を追加して、リポジトリの読解を助けてもらいましょう。そうしましょう。

LangChain公式のユースケースは基本的にはChatGPT APIを前提としています。GPT-3.5 turbo/GPT-4の能力を前提にしているということです。
ローカルLLMの能力は比較にならないほど低いので、Agentとして推敲(Chain-of-Thought)させることで何とか達成させます。

Embeddings

Retrieval Augment Generation (RAG)でLLMにドキュメント検索能力を持たせます。そのためにはembeddingsといって、テキストの類似度で検索できるデータベースを作成する必要があります。
HuggingFaceでembeddingsが無料で提供されているので、そちらを利用させていただきましょう。
HuggingFaceに登録してAPIキーを取得してください。
そして、ファイルにキーを書き込んで、そちらを参照するようにします。

# config.py
HUGGINGFACEHUB_API_TOKEN = "your_token_here"

参照したいリポジトリをgit cloneする

open-interpreterを参照しようと思います。
これはすごいツールなので、いろんな学びがありそうです。

git clone "https://github.com/KillianLucas/open-interpreter"

emeddingsで作成されたclone リポジトリのディレクトリを参照します。

Retriever

まずは検索に必要なemeddingsとretrieverを作成します。
repo_pathにcloneリポジトリのディレクトリを指定してください。

from langchain.tools import DuckDuckGoSearchRun
from langchain.agents import Tool, initialize_agent
from langchain.chains import LLMMathChain
from pydantic import BaseModel, Field

from langchain.llms import HuggingFacePipeline
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline

from langchain.document_loaders.generic import GenericLoader
from langchain.document_loaders.parsers import LanguageParser
from langchain.text_splitter import Language
from langchain.text_splitter import RecursiveCharacterTextSplitter

import os
from config import HUGGINGFACEHUB_API_TOKEN
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS

from langchain.agents.agent_toolkits import create_retriever_tool

# API TOKENS
os.environ["HUGGINGFACEHUB_API_TOKEN"] = HUGGINGFACEHUB_API_TOKEN

# git clone "https://github.com/KillianLucas/open-interpreter"
repo_path = "~/open-interpreter"

# Load
loader = GenericLoader.from_filesystem(
    repo_path + "/interpreter",
    glob="**/*",
    suffixes=[".py"],
    parser=LanguageParser(language=Language.PYTHON, parser_threshold=500),
)
documents = loader.load()

python_splitter = RecursiveCharacterTextSplitter.from_language(language=Language.PYTHON, chunk_size=2000, chunk_overlap=200)
texts = python_splitter.split_documents(documents)

# pip install sentence-transformers
embeddings = HuggingFaceEmbeddings()
# pip install faiss-cpu
db = FAISS.from_documents(texts, embeddings)
retriever = db.as_retriever()
retriever.search_kwargs["distance_metric"] = "cos"
retriever.search_kwargs["fetch_k"] = 20
retriever.search_kwargs["maximal_marginal_relevance"] = True
retriever.search_kwargs["k"] = 8

近傍探索にはMeta社が公開しているfaissを使用します。これも無料です。
faissをgpuで動作させる環境を整えるのは難しいので、cpuにしています。

LLM

# Local LLM
model_name_or_path = "TheBloke/openchat_3.5-GPTQ"
# To use a different branch, change revision
# For example: revision="gptq-4bit-32g-actorder_True"
model = AutoModelForCausalLM.from_pretrained(
    model_name_or_path,
    device_map="auto",
    trust_remote_code=False,
    revision="gptq-8bit-32g-actorder_True",
)
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, use_fast=True)

pipe = pipeline(
    "text-generation",
    model=model,
    tokenizer=tokenizer,
    max_new_tokens=512,
    do_sample=True,
    temperature=1.0,
    top_p=0.95,
    top_k=40,
    repetition_penalty=1.1,
)

llm = HuggingFacePipeline(pipeline=pipe)

Agent能力を満たすLLM "TheBloke/openchat_3.5-GPTQ"を使用します。

Tools

Agentが利用できるツールにリポジトリ検索ツールを追加します。

# Tools
tool = create_retriever_tool(
    retriever,
    "search-repository",
    "Searches and returns repository.",
)
tools = [tool]

# pip install duckduckgo-search
search = DuckDuckGoSearchRun()
tools.append(
    Tool(
        name="duckduckgo-search",
        func=search.run,
        description="useful for when you need to answer questions. You should ask targeted questions",
    )
)

# pip install numexpr
llm_math_chain = LLMMathChain.from_llm(llm=llm, verbose=True)
tools.append(
    Tool.from_function(
        func=llm_math_chain.run,
        name="Calculator",
        description="useful for when you need to answer questions about math",
    )
)

Agent

pythonのファイルを指定して、Agentに要約してもらいます。

# agent
agent = initialize_agent(
    tools,
    llm,
    agent="zero-shot-react-description",
    verbose=True,
    handle_parsing_errors=True,
)

text = "Summarize 'interpreter/core/code_interpreters/languages/powershell.py' in the repository."
output = agent.run(text)
output = output.split("\n")[0]
print(output)

Output


PowerShell.pyの概要が出力されました

Finished chain.
Create a PowerShell interpreter for executing PowerShell code and parsing the output from such execution.. A PowerShell interpreter is responsible for interpreting and executing PowerShell code and then parsing the resulting output. To achieve this, the interpreter uses the PowerShell library to interact with the PowerShell runtime. It processes the given code and determines which parts of the code correspond to active lines and the end of execution. In order to identify these parts, the interpreter utilizes various methods such as adding active line markers, wrapping code in a try-catch block, and checking for specific strings indicative of the end of execution or active lines. By doing so, it ensures accurate interpretation of the code and correct output extraction.

console

PowerShellコードを実行し、その出力を解析するためのPowerShellインタプリタを作成します。PowerShell インタプリタは、PowerShell コードを解釈して実行し、結果の出力を解析します。これを実現するために、インタプリタはPowerShellライブラリを使用してPowerShellランタイムと対話します。与えられたコードを処理し、コードのどの部分がアクティブ行と実行終了に対応するかを判断します。これらの部分を特定するために、インタプリタは、アクティブ行マーカーを追加する、try-catchブロックでコードをラップする、実行終了やアクティブ行を示す特定の文字列をチェックするなど、さまざまな方法を利用します。そうすることで、コードの正確な解釈と正しい出力の抽出が保証される。

deeplで翻訳

いいかんじです!第一歩としては上出来ではないでしょうか?

この記事が気に入ったらサポートをしてみませんか?