0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

社内PDFを外に出さない。サクッとOllama × AnythingLLM × GPU で完全ローカルRAGの文書内検索環境を作ってみる

0
Last updated at Posted at 2026-09-19

社内PDFを外に出さない。サクッとOllama × AnythingLLM × GPU で完全ローカルRAGの文書内検索環境を作ってみる

はじめに

社内のPDFをローカルLLMで検索したい、という話はよくあります。

実際にやってみると、LLMそのものよりも面倒なのはその前後でした。

  • PDFによっては文字が取れず、先にOCRが必要
  • AnythingLLMへ毎回手でアップロードするのが面倒
  • Workspaceへ入れたつもりでもEmbeddingできているか確認したい
  • 同じPDFをもう一度投入したくない
  • GPUごとにOllamaのモデルを切り替えたい
  • 何か失敗したときに、どこで止まったのか分かるようにしたい

数冊なら手作業でも何とかなりますが、これを何度も繰り返すのはつらいです。

そこで今回は、PDFを所定のフォルダへ置いてシェルスクリプトを1本実行すれば、OCR判定からAnythingLLM WorkspaceへのEmbeddingまで進むところまで自動化しました。

構成はすべてオンプレです。

  • Ubuntu 24.04 or wsl2
  • NVIDIA GPU
  • Docker Compose
  • Ollama
  • AnythingLLM
  • OCRmyPDF + Tesseract
  • Python製のPDF Ingestor

この記事では、最終的な構成だけでなく、実際にハマったところも含めて整理します。

この記事の実機確認環境

RTX 2080 SUPER 8GBで、qwen3:8b がOllama上で 100% GPU になるところまで確認しています。
RTX 4060 Ti 16GB向けのモデルプロファイルも同梱していますが、記事執筆時点での実機確認はRTX 2080 SUPER側が中心です。


サンプル一式のダウンロード

この記事で使用している local-ai-v2-gpu は、以下からダウンロードできます。

local-ai-v2-gpu.zip をダウンロード

ダウンロード後は、Ubuntu or wsl2 上で展開してプロジェクトディレクトリへ移動します。

unzip local-ai-v2-gpu.zip
cd local-ai-v2-gpu

以降は、この記事で説明するシェルスクリプトを順番に実行すれば環境を構築できます。


今回作ったもの

ざっくり言うと、次の流れを自動化しています。

20260918_r01.ong

RAGの検索精度そのものを自作するのではなく、役割を分けています。

自作部分
  └─ PDF判定 / OCR / 重複管理 / AnythingLLMへの自動登録

AnythingLLM
  └─ Workspace / Vector DB / RAG検索 / UI / プロンプト調整

Ollama
  └─ LLM / Embeddingモデルの推論

この分け方にしておくと、RAGの細かい調整はAnythingLLMの画面から行えます。


環境

今回のベース環境は次のとおりです。

項目 内容
OS Ubuntu 24.04
コンテナ Docker Engine + Docker Compose
GPU NVIDIA GPU
LLM Runtime Ollama
RAG UI AnythingLLM 1.16.1
Vector DB LanceDB(AnythingLLM組み込み)
OCR OCRmyPDF + Tesseract
PDF文字抽出 Poppler pdftotext
自動取込 Python 3.12

OllamaをDockerからNVIDIA GPUで動かすにはNVIDIA Container Toolkitが必要です。Ollama公式ドキュメントにもDocker + NVIDIA GPUの手順があります。

Ollamaのモデルはローカルで動作します。GPUへのロード状況は ollama ps で確認できます。


ディレクトリ構成

現在の local-ai-v2-gpu は次のような構成です。

local-ai-v2-gpu/
├── compose.yaml
├── .env.example
├── Makefile
│
├── scripts/
│   ├── 01_prepare.sh
│   ├── 02_build.sh
│   ├── 03_start.sh
│   ├── 04_doctor.sh
│   ├── 05_ingest.sh
│   ├── 06_status.sh
│   ├── 07_test.sh
│   ├── 08_logs.sh
│   ├── 09_stop.sh
│   ├── 10_model_profile.sh
│   ├── 11_models.sh
│   ├── 12_gpu_check.sh
│   └── 13_model_smoke_test.sh
│
├── model-profiles/
│   ├── rtx2080super.env
│   ├── rtx4060ti-fast.env
│   ├── rtx4060ti-balanced.env
│   ├── rtx4060ti-vision.env
│   └── rtx4060ti-quality.env
│
├── ingestor/
│   ├── Dockerfile
│   ├── requirements.txt
│   └── app/
│       ├── cli.py
│       ├── pipeline.py
│       ├── pdf_utils.py
│       ├── anythingllm.py
│       ├── manifest.py
│       ├── hashing.py
│       └── config.py
│
├── documents/
│   ├── input/
│   ├── processed/
│   └── failed/
│
├── data/
│   ├── ollama/
│   └── anythingllm/
│
├── state/
│   └── manifest.db
│
├── logs/
│   ├── ingestor.log
│   └── events.jsonl
│
└── tests/

PDFを触るときに直接意識するのは、ほぼこのフォルダだけです。

documents/input/

ここにPDFを置きます。


Docker Composeの構成

Composeでは3サービスに分けました。

20260918_r02.ong

ollama

LLMとEmbeddingモデルを実行します。

ollama:
  image: "${OLLAMA_IMAGE:-ollama/ollama:latest}"
  restart: unless-stopped
  ports:
    - "127.0.0.1:11434:11434"
  volumes:
    - ./data/ollama:/root/.ollama
  environment:
    OLLAMA_HOST: "0.0.0.0:11434"
    OLLAMA_CONTEXT_LENGTH: "${OLLAMA_CONTEXT_LENGTH:-8192}"
    OLLAMA_MAX_LOADED_MODELS: "${OLLAMA_MAX_LOADED_MODELS:-1}"
    OLLAMA_NUM_PARALLEL: "${OLLAMA_NUM_PARALLEL:-1}"
    OLLAMA_KEEP_ALIVE: "${OLLAMA_KEEP_ALIVE:-5m}"
    OLLAMA_FLASH_ATTENTION: "${OLLAMA_FLASH_ATTENTION:-1}"
  deploy:
    resources:
      reservations:
        devices:
          - driver: nvidia
            count: 1
            capabilities: [gpu]

ホスト側の11434番ポートは 127.0.0.1 にだけ公開しています。

Docker Compose内部では http://ollama:11434 でアクセスします。

anythingllm

AnythingLLMはUI、Workspace、RAG検索、LanceDB管理を担当します。

anythingllm:
  image: "${ANYTHINGLLM_IMAGE:-mintplexlabs/anythingllm:1.16.1}"
  restart: unless-stopped
  depends_on:
    - ollama
  ports:
    - "3001:3001"
  environment:
    STORAGE_DIR: "/app/server/storage"

    LLM_PROVIDER: "ollama"
    OLLAMA_BASE_PATH: "http://ollama:11434"
    OLLAMA_MODEL_PREF: "${OLLAMA_LLM_MODEL:-qwen3:14b}"
    OLLAMA_MODEL_TOKEN_LIMIT: "${OLLAMA_MODEL_TOKEN_LIMIT:-8192}"

    EMBEDDING_ENGINE: "ollama"
    EMBEDDING_BASE_PATH: "http://ollama:11434"
    EMBEDDING_MODEL_PREF: "${OLLAMA_EMBED_MODEL:-qwen3-embedding:4b}"
    EMBEDDING_MODEL_MAX_CHUNK_LENGTH: "${EMBEDDING_CHUNK_SIZE:-1000}"

    VECTOR_DB: "lancedb"

AnythingLLM公式の環境変数例では、EMBEDDING_MODEL_MAX_CHUNK_LENGTH はEmbeddingする文字列の最大チャンクサイズ(文字数)として定義されています。

ingestor

PDFを自動処理するための自作コンテナです。

普段は常駐させません。

05_ingest.sh
  ↓
docker compose run --rm --no-deps ingestor ingest

という形で、必要なときだけ起動します。


.env でモデルやOCR設定を切り替える

モデル名をComposeへ直接書かず、.env に寄せています。

たとえばRTX 2080 SUPER 8GBでは次の設定を使っています。

MODEL_PROFILE=rtx2080super

OLLAMA_LLM_MODEL=qwen3:8b
OLLAMA_EMBED_MODEL=qwen3-embedding:0.6b

OLLAMA_MODEL_TOKEN_LIMIT=4096
OLLAMA_CONTEXT_LENGTH=4096

OLLAMA_MAX_LOADED_MODELS=1
OLLAMA_NUM_PARALLEL=1
OLLAMA_KEEP_ALIVE=5m
OLLAMA_FLASH_ATTENTION=0

RTX 4060 Ti 16GB用には別プロファイルを用意しています。

MODEL_PROFILE=rtx4060ti-balanced

OLLAMA_LLM_MODEL=qwen3:14b
OLLAMA_EMBED_MODEL=qwen3-embedding:4b

OLLAMA_MODEL_TOKEN_LIMIT=8192
OLLAMA_CONTEXT_LENGTH=8192

OLLAMA_MAX_LOADED_MODELS=1
OLLAMA_NUM_PARALLEL=1
OLLAMA_KEEP_ALIVE=5m
OLLAMA_FLASH_ATTENTION=1

Ollama公式ライブラリ上では、記事執筆時点で次のサイズになっています。

  • qwen3:14b:約9.3GB
  • qwen3-embedding:0.6b:約639MB
  • qwen3-embedding:4b:約2.5GB

参考:

モデルを直接書き換えなくてもよいようにした

GPUごとにプリセットがあります。

./scripts/10_model_profile.sh list

RTX 2080 SUPERなら、

./scripts/10_model_profile.sh rtx2080super

RTX 4060 Tiなら、

./scripts/10_model_profile.sh rtx4060ti-balanced

現在値は、

./scripts/10_model_profile.sh show

で確認できます。

GPUメモリから候補を選ぶ補助機能もあります。

./scripts/10_model_profile.sh detect

ただし detect はあくまで候補選択です。適用後は show で必ず確認しています。


初回セットアップ

1. 準備

cd ~/local-ai-v2-gpu
./scripts/01_prepare.sh

このスクリプトでは、

  • documents/input
  • documents/processed
  • documents/failed
  • data/ollama
  • data/anythingllm
  • state
  • logs

を作り、.env がなければ .env.example から作成します。

既存の .env は上書きしません。

2. GPUプロファイルを選ぶ

RTX 2080 SUPERなら、

./scripts/10_model_profile.sh rtx2080super

設定確認:

./scripts/10_model_profile.sh show

3. ビルド

./scripts/02_build.sh

内部では、まずCompose設定を検証します。

docker compose config

その後、

docker compose pull ollama anythingllm
docker compose build ingestor

を実行します。

4. 起動

./scripts/03_start.sh

このスクリプトは単純に docker compose up -d をするだけではありません。

処理順は次のとおりです。

20260918_r03.ong

モデルを先に取得してからAnythingLLMを起動するようにしたのは、初回起動時の切り分けを楽にするためです。


AnythingLLMのDeveloper APIキーを1回だけ設定する

自動取込では、ブラウザ操作ではなくAnythingLLMのDeveloper APIを使います。

AnythingLLMのOpenAPI定義には、文書Upload用の次のAPIがあります。

POST /api/v1/document/upload

addToWorkspaces にWorkspace slugを渡すと、Upload後にWorkspaceへ登録できます。

公式OpenAPI:

APIを操作するため、初回だけDeveloper APIキーを作ります。

AnythingLLMを起動して、ブラウザから、

Settings
  ↓
Developer API
  ↓
API Keyを作成

と進みます。

作ったキーを .env に設定します。

ANYTHINGLLM_API_KEY="ここにAPIキー"
WORKSPACE_SLUG=pdf-rag
WORKSPACE_NAME="PDF RAG"
AUTO_CREATE_WORKSPACE=true

このAPIキーはOpenAIなど外部サービスのキーではありません。

ローカルのAnythingLLMを自動操作するための認証情報です。

なお、APIキーを記事、Git、ログへ載せないようにします。

chmod 600 .env

としておくのもよいと思います。

APIキーを設定したら、AnythingLLMを再起動する必要はありません。


04_doctor.sh で接続確認

./scripts/04_doctor.sh

このスクリプトでは、少なくとも次を確認します。

  • .env にAPIキーがあるか
  • Ollamaが起動中か
  • AnythingLLMが起動中か
  • AnythingLLM Developer APIへ認証できるか
  • Workspaceが存在するか
  • Ollama APIへ接続できるか
  • 指定したLLMモデルが存在するか
  • 指定したEmbeddingモデルが存在するか
  • Embedding APIが実行できるか

正常なら最後に、

DOCTOR: PASS

となります。

PDFを何十分もOCRしたあとにAPIキーエラーになると悲しいので、取込前に接続確認するようにしています。


PDFを投入する

PDFはここへ置きます。

documents/input/

例:

documents/input/
├── 河川整備計画.pdf
├── 河川基本方針.pdf
└── 報告書.pdf

サブディレクトリも再帰的に検索します。

OllamaとAnythingLLMは起動したままでOKです。


05_ingest.sh で一括取込

実際の運用では、ほぼこれだけです。

./scripts/05_ingest.sh

内部では最初にAPIキーを検証します。

AnythingLLM API key: OK
Starting PDF ingestion without restarting Ollama/AnythingLLM...

そのあとIngestorだけを一時コンテナとして起動します。

docker compose run --rm --no-deps ingestor ingest

ここで --no-deps が重要です。

以前、単純に docker compose run ingestor としたところ、取込時にOllamaとAnythingLLMまで再作成されてしまいました。

PDFを追加するたびにLLMやUIを再起動する必要はないので、現在は既存サービスをそのまま使います。

実際の実行例

画像PDFを2冊入れたときは、次のように処理されました。

[1/2] Processing 河川基本方針.pdf
OCR required: 河川基本方針.pdf -> 河川基本方針_ocr.pdf
Uploaded to AnythingLLM: ...
OK embedded: 河川基本方針.pdf

[2/2] Processing 河川整備計画.pdf
OCR required: 河川整備計画.pdf -> 河川整備計画_ocr.pdf
Uploaded to AnythingLLM: ...
OK embedded: 河川整備計画.pdf

SUMMARY discovered=2 embedded=2 skipped=0 failed=0

これで、

PDF検出
 ↓
OCR
 ↓
AnythingLLM Upload
 ↓
Workspace Embedding

まで通っています。


OCRが必要かどうかは自動判定する

PDFだからといって、必ず文字データが入っているわけではありません。

紙資料をスキャンしただけのPDFでは、見た目は普通でも pdftotext では何も取れないことがあります。

そこでまず、

pdftotext

相当の処理を行い、抽出文字数を確認します。

初期値は、

MIN_TEXT_CHARS=200

です。

これより少なければOCR対象にします。

PDF
 ↓
pdftotext
 ↓
文字数 >= 200 ?
 ├─ Yes → そのままAnythingLLMへ
 └─ No  → OCRmyPDF

OCRは、

OCR_LANGUAGES=jpn+eng
OCR_MODE=force

を初期値にしています。

OCR後も再度文字抽出を行い、

OCR_MIN_TEXT_CHARS=300

を満たさなければ失敗扱いにします。

「OCRコマンドが終了コード0だったから成功」ではなく、実際に検索可能な文字が取れたかまで確認する形です。


OCRmyPDFのバージョン差で一度ハマった

最初は、

--mode force

を使っていました。

ところがIngestorコンテナ内のOCRmyPDFでは、

OCRmyPDF: error: unrecognized arguments: --mode

となりました。

OCRmyPDFの --mode は17.0.0で追加されたオプションです。

公式ドキュメントでは、従来の、

--force-ocr
--skip-text
--redo-ocr

は後方互換用のエイリアスとして残っています。

そのため現在は、設定値を次のように変換しています。

force -> --force-ocr
skip  -> --skip-text
redo  -> --redo-ocr

これで旧版・新版の両方を扱いやすくしました。

参考:


同じPDFを何度もEmbeddingしない

PDFごとにSHA256を計算しています。

PDF
 ↓
SHA256
 ↓
manifest.dbを確認
 ↓
すでにembeddedならSKIP

状態はSQLiteへ保存します。

state/manifest.db

同じPDFを再度投入した場合は、

SKIP report.pdf (same SHA256 already embedded)

となります。

強制的に再登録したい場合は、

FORCE_REINGEST=true

にします。

Chunk Sizeを変えて再Embeddingしたい場合などに使えます。


AnythingLLMのRAG設定

ここからが「検索精度」の調整です。

Ingestor側は、正しい文書をAnythingLLMへ届けるところまでに留めています。

検索精度はAnythingLLMのWorkspace設定で調整します。

まずAgentモードを使わない

ここはかなり重要でした。

最初、Workspaceのチャットモードが「代理人(Agent)」になっていました。

たとえば、

馬込川の流路延長は?

という単純な質問でも、Agentが、

rag-memory
 ↓
document-summarizer
 ↓
PDF全文を11セクションに分割
 ↓
各セクションを順番に要約

という処理を始めました。

結果として、回答まで1分以上かかりました。

AgentはWeb検索やツール実行などには便利ですが、技術PDFから数値を1つ探す用途には重すぎました。

AnythingLLMのAgentはスキルやツールを呼び出す機能です。

PDF RAG用Workspaceでは、まず「クエリ」を使います。

Workspace設定
  ↓
チャット設定
  ↓
チャットモード
  ↓
クエリ

今回の用途では、

質問
 ↓
Vector Search
 ↓
関連Chunk
 ↓
qwen3:8b
 ↓
回答

というシンプルな流れにした方が速く、挙動も分かりやすかったです。

RTX 2080 SUPERでの設定例

現在は次を初期値にしています。

設定 値
Workspace LLM Provider Ollama
Workspace Chat Model qwen3:8b
Chat Mode クエリ
Chat History 6程度
Temperature 0.1〜0.2
Embedding qwen3-embedding:0.6b

温度は、創作ではなく数値・記述の抽出が目的なので低めにしています。

System Prompt

WorkspaceのPromptは次のようにしています。

あなたはWorkspaceに登録された技術文書から事実を検索して回答するアシスタントです。

質問に関係する文書の箇所を検索し、その内容だけを根拠に回答してください。
文書全体の要約は、ユーザーが明示的に要約を要求した場合だけ行ってください。

数値を質問された場合は、該当する数値、単位、対象項目を明記してください。
複数の異なる記述がある場合は、勝手に統合せず、それぞれを示してください。
文書から確認できない場合のみ「登録文書からは確認できません」と回答してください。
推測や一般知識による補完は行わないでください。
可能な場合は出典を示してください。

Queryモードの拒否応答も日本語にしておくと分かりやすいです。

登録文書からは、質問に回答できる情報を確認できませんでした。

Chunk Sizeは1000文字から試している

最初はAnythingLLM側で、長いPDFが数個の大きなSnippetにしか分割されていませんでした。

これでは、

流域面積は?

のようなピンポイント検索で、必要な箇所を拾いにくくなります。

現在は、

EMBEDDING_CHUNK_SIZE=1000

としています。

Composeでは、

EMBEDDING_MODEL_MAX_CHUNK_LENGTH=1000

としてAnythingLLMへ渡します。

AnythingLLM公式の .env.example では、この値はEmbedding対象文字列の最大チャンクサイズ(chars)として説明されています。

まず1000文字で始め、

1000
1500
2000

のように比較していく想定です。

Chunk Sizeを変更した場合は、既存ベクトルをそのまま使うのではなく対象文書を再Embeddingします。


Vector検索設定の初期値

現在は次を基準にしています。

Search Preference      Default
Max Context Snippets   4〜6
Similarity Threshold   0.25付近から開始
LLM Temperature        0.1〜0.2

ここは「大きくすれば精度が上がる」という単純なものではありません。

評価用の質問をあらかじめ作り、設定を1個ずつ変える方が分かりやすいです。

たとえば、

文書に確実に存在する質問      10問
文書に存在しない質問          2〜3問

を作り、

  • 正しい数値が取れるか
  • 関係ない文書を拾わないか
  • 文書にない場合に「ない」と答えられるか

を見ています。


RTX 2080 SUPERでGPU実行を確認する

モデルを入れただけでは、GPUで全部動いているとは限りません。

確認は、

docker compose exec -T ollama ollama ps

です。

実機では次の状態を確認できました。

NAME        SIZE      PROCESSOR    CONTEXT
qwen3:8b    6.2 GB    100% GPU     8192

さらに、

nvidia-smi

では、Ollamaの llama-server が約6GBのVRAMを使用していました。

つまり、qwen3:8b 自体はRTX 2080 SUPER 8GBでGPU内に収まっています。

なお、.env で4096を指定していても、クライアント側がAPIリクエストで num_ctx を指定すると実際のContextが変わることがあります。

Ollama公式にも、Contextは環境変数だけでなくAPIの num_ctx でも指定できるとあります。

そのため、実際に使われているContextは、

ollama ps

で確認するのが確実です。


モデル関連のシェルスクリプト

10_model_profile.sh

GPU別のモデルプリセットを .env に反映します。

./scripts/10_model_profile.sh list
./scripts/10_model_profile.sh show
./scripts/10_model_profile.sh detect
./scripts/10_model_profile.sh rtx2080super
./scripts/10_model_profile.sh rtx4060ti-balanced

11_models.sh

モデル設定やOllama上のモデル状態を確認します。

./scripts/11_models.sh show
./scripts/11_models.sh list
./scripts/11_models.sh ps
./scripts/11_models.sh pull

12_gpu_check.sh

ホストGPU、DockerからのGPUアクセス、Ollamaのロード状況をまとめて確認します。

./scripts/12_gpu_check.sh

内部では、

nvidia-smi

に加えて、

docker run --rm --gpus all ubuntu:24.04 nvidia-smi -L

も実行します。

13_model_smoke_test.sh

LLMとEmbeddingモデルの両方を実際に叩きます。

./scripts/13_model_smoke_test.sh

LLMには短い日本語生成をさせ、Embeddingには、

馬込川水系河川整備計画 流域面積

という文字列を渡してベクトルが返ることを確認します。

最後に、

MODEL SMOKE TEST: PASS

になればOKです。


その他の運用スクリプト

スクリプト 用途
01_prepare.sh ディレクトリと.envの初期準備
02_build.sh Compose検証、Image pull、Ingestor build
03_start.sh Ollama→モデルpull→AnythingLLMの順に起動
04_doctor.sh API、モデル、Embeddingの診断
05_ingest.sh PDFのOCR・Upload・Embedding
06_status.sh manifestの処理状態確認
07_test.sh pytest実行
08_logs.sh Ollama / AnythingLLMのログ確認
09_stop.sh docker compose down
10_model_profile.sh GPU別モデル設定切替
11_models.sh モデル状態確認・pull
12_gpu_check.sh GPU確認
13_model_smoke_test.sh LLM/Embedding実推論テスト

ログを見る

./scripts/08_logs.sh

状態を見る

./scripts/06_status.sh

停止

./scripts/09_stop.sh

データはbind mountしているので、コンテナを落としてもOllamaモデルやAnythingLLMのデータは残ります。


テスト

自動化部分はpytestでテストしています。

./scripts/07_test.sh

記事執筆時点のプロジェクトでは、

37 passed

を確認しています。

対象には、

  • PDF文字抽出判定
  • OCR分岐
  • SHA256重複判定
  • manifest更新
  • AnythingLLM APIレスポンス処理
  • モデルプロファイル切替
  • Compose設定
  • .env のshell互換性
  • OCRmyPDFの旧CLI互換性

などを含めています。

加えて実機では、2冊の画像PDFに対して、

SUMMARY discovered=2 embedded=2 skipped=0 failed=0

まで確認しました。

単体テストだけでなく、最終的には実際のGPU、実際のPDF、実際のAnythingLLMまで通すのが大事です。


実際にハマったところ

1. .env の空白

最初、

WORKSPACE_NAME=PDF RAG

としていました。

シェルで source .env すると、RAG をコマンドとして解釈します。

正しくは、

WORKSPACE_NAME="PDF RAG"

です。

.env をシェルから読む構成では、このあたりもテストした方が安全でした。

2. container_name を固定すると古いコンテナと衝突する

以前の環境に停止済みの /ollama が残っていると、

Conflict. The container name "/ollama" is already in use

となりました。

現在は、

container_name: ollama

のような固定名を使っていません。

代わりに、

COMPOSE_PROJECT_NAME=local-ai-v2-gpu

でComposeプロジェクトとして管理します。

3. PDF投入時にOllamaまで再作成してしまった

docker compose run の使い方によっては依存サービスまで再作成されることがあります。

現在は、

docker compose run --rm --no-deps ingestor ingest

にして、AnythingLLM/Ollamaを起動したまま処理します。

4. 画像PDFをそのままAnythingLLMへ入れても検索できない

見た目がPDFでも、文字レイヤーがなければRAG検索に必要な文字列がありません。

今回の構成でOCRを前段に置いた一番大きな理由です。

5. Agentモードは何でも速くしてくれるわけではない

PDF内の数値検索でAgentモードを使ったところ、全文要約ツールまで呼び出してしまいました。

「Agentだから高精度」と決めつけず、単純な文書RAGではQueryモードから始めた方が扱いやすいと感じました。


普段の使い方はかなり単純になった

初回セットアップが終わった後は、普段やることはほぼ次だけです。

サービスを起動

./scripts/03_start.sh

PDFを置く

documents/input/

登録

./scripts/05_ingest.sh

AnythingLLMで質問

http://<UbuntuのIP>:3001

これだけです。

手作業で、

PDFを開く
 ↓
文字PDFか確認
 ↓
OCRする
 ↓
AnythingLLMへUpload
 ↓
Workspaceへ移動
 ↓
Embedding

とやっていた部分をかなり減らせました。


今後やりたいこと

現状はプロトタイプですが、次はこのあたりを考えています。

  • RAG評価用の質問セットを自動実行する
  • Chunk Sizeごとの正答率比較
  • Embeddingモデルの比較
  • 出典ページ番号をもっと確実に返す仕組み
  • PDF以外のDOCX、Excel、Markdown対応
  • フォルダ監視による自動投入
  • 大量PDF向けのCelery非同期化
  • Workspaceごとの自動振り分け
  • RTX 4060 Ti 16GB実機での14Bモデル評価

ただし、最初から全部を作るより、今のように、

PDF前処理は自作
RAG/UIはAnythingLLM
推論はOllama

と役割分担した方が、検証しやすいと思っています。


まとめ

今回やりたかったのは、単に「AnythingLLMをDockerで起動する」ことではありませんでした。

実際に使い続けるには、

  • スキャンPDFを自動OCRする
  • 同じPDFを二重登録しない
  • GPUごとにモデルを変える
  • AnythingLLM APIでWorkspaceへ自動登録する
  • 失敗箇所をログで追えるようにする
  • RAGの精度調整はUI側へ残す

といった周辺部分が必要でした。

現在は、PDFを documents/input/ に置いて、

./scripts/05_ingest.sh

を実行すれば、OCRからWorkspaceへのEmbeddingまで進められます。

RTX 2080 SUPER 8GBでも qwen3:8b を100% GPUで動かせるところまで確認できました。

大きなモデルを無理に載せるより、まずは8BクラスでRAGの検索経路、Chunk、Embedding、プロンプトを整える方が、文書検索用途では効果が大きそうです。

ローカルRAGはLLMを起動して終わりではなく、「文書をどう確実に入れるか」まで自動化すると一気に使いやすくなる、というのが今回一番大きかったところです。


参考


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?