LlamaIndexでネットワーク接続なし,ローカルで日本語で独自項目をAI回答させる

# はじめに

自社システムのFAQとして日本語AI回答機能を追加する場合、**LlamaIndex**で実現可能
との記事がありましたので参考にして試してみました。
結果、たしかにネットワーク接続なし (LANケーブル接続なし) 環境でも日本語で質問すると
日本語で回答してくれることが分りました。
質問と回答の組み合わせを自分で登録しておけるので、これは使えそうな気がします。
今回試した手順を残します。

# 前提

Windows 環境 Python **3.10.11** を使用します。
Microsoft Store からインストールでも、別の方法でも問題なし。
venv で仮想環境を構築し、そこで作業することにします。

# フォルダ構成 (最終的にこうなります)
![0018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/d6ba2130-4a92-5a03-579d-a7e31fd14634.png)

#### 1.inputs
質問と回答の組み合わせを記載したファイルを配置します。
![0019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/a2c646f4-f19a-346b-6648-9188904fc303.png)

#### 2.models
モデル形式ファイルを配置します。
今回は別記事 (**LM Studioでローカル環境でLLMを動かす手順について** 
https://qiita.com/kharada_toyotec/items/d81214234bc429475789) でダウンロードした **ELYZA-japanese-Llama-2-7b-fast-instruct-q4_K_M.gguf** を使用します。
![0020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/7815ae52-4650-b45a-ce9c-bf1dbcb4f8ea.png)

# 仮想環境 (venv) 設定

#### 1.ルートフォルダ
今回は Dドライブに **Python\LlamaIndexSample** フォルダを作成し、そこで作業します。

#### 2.venv作成
```cmd:実行例
python -m venv .venv
```
![0001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/9423bfb8-a8aa-24ce-86a1-84e3256524d0.png)

#### 3.activate
```cmd:実行例
.venv\Scripts\activate
```
![0002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/c6c690cd-cbb3-dc8f-0741-435727671ab3.png)

行の先頭が (.env) に変わります。
![0003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/dd6f4916-de62-a082-9c5c-c4f971d7c124.png)

# 必要なライブラリをインストール

#### 1.transformers accelerate bitsandbytes
```cmd:実行例
pip install transformers accelerate bitsandbytes
```
![0004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/bd2bd60f-a27b-1e04-3d29-91f8d24d5def.png)

#### 2.torch torchvision torchaudio

```cmd:実行例
python -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
```
![0008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/cf73da8b-61e0-bde6-fbf7-3076d565e73a.png)

#### 3.langchain

```cmd:実行例
pip install langchain
```
![0010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/90805071-9f56-0b56-6686-fbffbceafc2c.png)

#### 4.llama_index
```cmd:実行例
pip install llama_index
```
![0012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/3b90098d-4ce2-2712-2db8-1514143ecc71.png)

#### 5.llama-cpp-python
```cmd:実行例
pip install llama-cpp-python
```
![0014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/af0ed239-b3f4-4265-1c7d-0f505996be8d.png)

#### 6.sentence-transformers
```cmd:実行例
pip install sentence-transformers
```
![0016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/a43afaad-19c8-c61e-464c-2ad79931026d.png)


# 実行するプログラム
```py:記述例 (main.py)
from llama_index import LLMPredictor, ServiceContext, SimpleDirectoryReader, GPTVectorStoreIndex
from llama_index.embeddings import LangchainEmbedding

from llama_index.prompts.prompts import QuestionAnswerPrompt

from langchain.llms import LlamaCpp
#from langchain_community.llms import LlamaCpp
from langchain.embeddings.huggingface import HuggingFaceEmbeddings

llm             = LlamaCpp(model_path=f'./models/ELYZA-japanese-Llama-2-7b-fast-instruct-q4_K_M.gguf', temperature=0, n_ctx=4096, n_gpu_layers=1)
llm_predictor   = LLMPredictor(llm=llm)
embed_model     = LangchainEmbedding(HuggingFaceEmbeddings(model_name="intfloat/multilingual-e5-base"))
service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor, embed_model=embed_model)

# ドキュメントのインデックス化
documents = SimpleDirectoryReader('./inputs').load_data()
index     = GPTVectorStoreIndex.from_documents(documents, service_context=service_context)

# 質問
temp = """


 

あなたは誠実で優秀な日本人のアシスタントです。
以下の「コンテキスト情報」と「制約条件」を元に質問に回答してください。

# コンテキスト情報

---------------------
{context_str}
---------------------

# 制約条件

- コンテキスト情報はマークダウン形式で書かれています。
- 「コンテキスト情報に」のような書き方を絶対に回答に含めないでください。
- コンテキスト情報に無い情報は絶対に回答に含めないでください。
- コンテキスト情報の内容を丸投げするのではなく、絶対にきちんとした文章にして回答してください。
- 質問の答えを知らない場合は、誤った情報を共有しないでください。



{query_str} 

"""
query_engine = index.as_query_engine(text_qa_template=QuestionAnswerPrompt(temp))
while True:
    req_msg = input('\n## Question: ')
    res_msg = query_engine.query(req_msg)
    print('\n##', str(res_msg).strip())
```

# 質問と回答の組み合わせ
```md:記述例 (〇〇システムFAQ.md)
# 〇〇システム FAQ

## こんなときは

### 問合せ先を知りたい

- ■×株式会社（ＴＥＬ　０００－１１１－２２２２、ＦＡＸ　０００－１１１－９９９９） へ連絡ください。

### ログインできない

- キーボードのCapsLockがONになっていないか確認いただき、ユーザID、パスワードに誤りがないか再確認してください。

### 他の端末で使用中と表示される

- 対象プログラムの「ロック区分」を確認いただき、「処理中」の場合は「通常状態」に戻し、再実行してください。
```

# プログラム実行

実際に実行してみます。
**それほど待たずに回答がきます。**
```cmd:実行例
python main.py
```
![0021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/b719e6c4-c6ea-8143-8594-3395bad62e81.png)

#### 「##Question: 」で止まり、質問受付状態となります。
![0022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/c7c988c9-7f6a-0926-bfcd-bc24b6c532bd.png)

#### 質問してみます。
大きな問題はなさそう。
![0023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/070b1f7f-5254-bea1-d6d2-e93e4b482e2a.png)

#### 続けて質問してみます。
これも特に問題なさそう。
![0024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/4f120296-9ff3-bf04-8ed8-c1d0313cf738.png)

#### 最後の質問。
質問と回答の組み合わせで登録した内容以外に余計な回答 (Windowsの場合～) が返りました。
これはイマイチです。
![0025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3668873/87bce337-c43f-7f06-e400-18766f3ba597.png)

# 最後に
改善する必要はありそうですが、ネットワークに接続していない環境で使えることが分りました。
使い道は色々とありそうです。

## 参考文献
この記事は以下の情報を参考にして執筆しました。
- [LlamaIndexを使って独自データをQ&AするだけならOpenAI API使わなくてもいいでない？](https://qiita.com/yagisawa/items/b212460d440e4b240fc3)