Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,28 @@ KAFKA_BOOTSTRAP_SERVERS=kafka:9092
LLM_BACKEND=ollama

# --- Ollama (if LLM_BACKEND=ollama) ---
# Containerised Ollama on the compose network (default). NOTE: on macOS and
# Windows this runs CPU-only — Docker's Linux VM cannot reach the host GPU.
OLLAMA_URL=http://ollama:11434
# For GPU-accelerated local inference, run Ollama natively on the host, start
# the stack WITHOUT the local-llm profile, and use the host address instead:
# OLLAMA_URL=http://host.docker.internal:11434
# Some runtimes (OrbStack) forward host.docker.internal to the host loopback,
# so a server bound to 127.0.0.1 works as-is. On Docker Desktop the native
# server must listen on all interfaces instead, which exposes it to the LAN:
# OLLAMA_HOST=0.0.0.0:11434 ollama serve
OLLAMA_MODEL=mistral:7b
# Host port for the containerised Ollama. Deliberately NOT 11434 by default:
# the container binds all interfaces (including IPv6), so publishing 11434
# would shadow a natively installed Ollama whenever you use "localhost".
# OLLAMA_HOST_PORT=127.0.0.1:11435
# Context window Ollama allocates for a request. The whole RAG prompt must fit:
# roughly top_k x 512 tokens of chunks, plus injected XBRL facts, plus the
# system prompt, plus the 1024-token answer budget. Ollama's own default (4096)
# truncates the START of the prompt — silently dropping the system prompt and
# the citation instruction. 8192 covers top_k up to ~10; raise it for larger
# top_k (costs RAM for the KV cache).
OLLAMA_NUM_CTX=8192

# --- OpenAI (if LLM_BACKEND=openai) ---
OPENAI_API_KEY=
Expand Down Expand Up @@ -69,5 +89,28 @@ EDGAR_RATE_LIMIT_RPS=10
# EVAL_OLLAMA_URL=http://localhost:11434
# EVAL_OLLAMA_MODEL=mistral:7b

# --- Resource limits / performance tuning ---
# Defaults are conservative so the stack starts on a modest machine. Scale
# these to your hardware. A memory limit larger than the container runtime's
# own VM allowance is silently ignored — check `docker info` first.
# POSTGRES_CPUS=4.0
# POSTGRES_MEMORY=8G
# POSTGRES_SHARED_BUFFERS=2GB
# POSTGRES_WORK_MEM=256MB
# POSTGRES_MAINTENANCE_WORK_MEM=1GB
# POSTGRES_EFFECTIVE_CACHE_SIZE=4GB
# POSTGRES_PARALLEL_WORKERS_PER_GATHER=2
# KAFKA_CPUS=2.0
# KAFKA_MEMORY=4G
# INGESTION_CPUS=2.0
# INGESTION_MEMORY=2G
# EMBEDDING_WORKER_CPUS=12.0
# EMBEDDING_WORKER_MEMORY=6G
# Retrieval runs in a thread pool, so this caps concurrent query throughput.
# QUERY_API_CPUS=4.0
# QUERY_API_MEMORY=4G
# OLLAMA_CPUS=8.0
# OLLAMA_MEMORY=8G

# --- Logging ---
LOG_LEVEL=INFO
28 changes: 24 additions & 4 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ API Client <--> Query API <--> Ollama / OpenAI / Claude |
- Python 3.12 以降(ローカル開発および Docker 外でのテスト実行用)
- GNU Make(任意、便利なターゲット用)

**ハードウェア(Ollama / ローカル LLM パスの場合のみ):** `make run` は `mistral:7b`(約 4 GB のダウンロード)を取得し、実行時に少なくとも **8 GB の空き RAM** が必要です(モデルの重み + Docker オーバーヘッド)。RAM が不足しているマシンでは Ollama コンテナが OOM で強制終了されます。リモート LLM パス(`LLM_BACKEND=claude` または `openai` を指定した `make run-remote`)では、ベーススタック(約 2 GB)以外に GPU や RAM の要件はありません。
**ハードウェア:** 本スタックは実行するマシンに合わせてサイズを調整できます。コンテナの CPU およびメモリ上限、埋め込みのバッチサイズ、Ollama のコンテキストウィンドウはすべて環境変数です([設定](#設定)を参照)。手持ちのハードウェアに合わせてスケールしてください。必要なリソースは、選択する LLM バックエンドにほぼ完全に依存します。`LLM_BACKEND=claude` または `openai` を指定した `make run-remote` はローカル推論を一切行いません。一方、ローカル LLM パスは選択したモデルによって決まります。

ローカルでベンチマークを取る前に知っておくべき注意点が 1 つあります。**macOS および Windows では、コンテナ化された Ollama は CPU のみで動作します**。Docker の Linux VM はホストの GPU にアクセスできないためです。ローカル生成を大幅に高速化するには、ホスト上で Ollama をネイティブに実行し、`OLLAMA_URL` をそこに向けてください。[LLM バックエンド](#llm-バックエンド)を参照してください。

## クイックスタート

Expand Down Expand Up @@ -64,7 +66,7 @@ make run-remote

初回起動時は、コンテナイメージのプル、3 つのサービスのビルド、データベースマイグレーションの実行が行われます。スキーマは `db/migrations/001_initial_schema.sql` から自動的に適用されます(`pgvector` 拡張、`ingestion_log` テーブル、`document_chunks` テーブル、HNSW ベクターインデックスを作成します)。マイグレーションを手動で実行するには:`make migrate`

Ollama を使用する場合(`make run`)、`mistral:7b` モデル(約 4 GB)は初回起動時に自動的にダウンロードされます。2 回目以降の起動ではキャッシュされたレイヤーとボリュームが再利用されます。
Ollama を使用する場合(`make run`)、`OLLAMA_MODEL` で指定したモデルが初回起動時に自動的にダウンロードされます。2 回目以降の起動ではキャッシュされたレイヤーとボリュームが再利用されます。

4. サービスが起動していることを確認します。

Expand Down Expand Up @@ -350,7 +352,20 @@ make helm-teardown
| `OPENAI_MODEL` | `gpt-4o-mini` | OpenAI モデル名 |
| `ANTHROPIC_API_KEY` | (空) | `LLM_BACKEND=claude` 時に必須 |
| `CLAUDE_MODEL` | `claude-opus-4-6` | Claude モデル名 |
| `EMBEDDING_MODEL` | `sentence-transformers/all-MiniLM-L6-v2` | 埋め込み用 sentence-transformers モデル |
| `EMBEDDING_MODEL` | `nomic-ai/nomic-embed-text-v1.5` | 埋め込み用 sentence-transformers モデル(768 次元) |

**パフォーマンスチューニング**

実行するマシンに合わせてスケールしてください。デフォルト値はどの環境でも起動できるよう控えめに設定されています。

| 変数 | デフォルト | 説明 |
| ------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------- |
| `OLLAMA_NUM_CTX` | `8192` | Ollama に要求するコンテキストウィンドウ。RAG プロンプト全体が収まらない場合、先頭から切り捨てられシステムプロンプトが失われます。 |
| `EMBEDDING_BATCH_SIZE` | `64` | 埋め込みワーカーが 1 バッチで処理するチャンク数。大きくするとスループットが向上しますが、メモリを消費します。 |
| `POSTGRES_SHARED_BUFFERS` | `2GB` | PostgreSQL のページキャッシュ。コーパスがこれを超えてから引き上げる価値があります。 |
| `POSTGRES_WORK_MEM` | `256MB` | PostgreSQL の操作あたりのソート / ハッシュ用メモリ。 |
| `QUERY_API_CPUS` | `4.0` | Query API コンテナの CPU 上限。検索はスレッドプールで実行されるため、同時クエリのスループットを制限します。 |
| `EMBEDDING_WORKER_CPUS` | `12.0` | 埋め込みワーカーコンテナの CPU 上限。 |

**セキュリティと API**

Expand Down Expand Up @@ -389,7 +404,12 @@ make helm-teardown

Query API は `LLM_BACKEND` 環境変数で選択可能な 3 つの LLM バックエンドをサポートします。

**Ollama(デフォルト)** -- Docker Compose スタック内でローカルに実行されます。API キー不要。モデルは初回起動時に自動的に取得されます。`make run`(または `docker compose --profile local-llm up`)で起動します。開発環境およびセルフホスト型デプロイに適しています。`mistral:7b` のモデルウェイトには約 6 GB の RAM が必要です(Docker オーバーヘッドを含む合計では約 8 GB)。
**Ollama(デフォルト)** -- ローカルで実行され、API キーは不要です。`OLLAMA_MODEL` で指定したモデルは初回起動時に自動的に取得されます。開発環境およびセルフホスト型デプロイに適しています。実行方法は 2 通りあります。

- *コンテナ化*(`make run`、または `docker compose --profile local-llm up`)— セットアップ不要で完全にポータブルです。ただし macOS および Windows では推論が **CPU のみ** で実行されます。Docker の Linux VM はホストの GPU にアクセスできないため、コンテナに CPU やメモリをどれだけ割り当てても生成は低速です。
- *ホストネイティブ* — ホスト上で `ollama serve` を実行してホストの GPU(macOS では Metal、Linux では CUDA / ROCm)を利用し、`local-llm` プロファイル **なし** でスタックを起動して(`make run-remote`)、`OLLAMA_URL=http://host.docker.internal:11434` を設定します。この方法は通常、コンテナ化パスより一桁高速です。一部のランタイム(OrbStack)は `host.docker.internal` をホストのループバックに転送するため、`127.0.0.1` にバインドされたサーバーにそのまま到達できます。Docker Desktop の場合はネイティブサーバーをすべてのインターフェースで待ち受けさせる必要があります(`OLLAMA_HOST=0.0.0.0:11434`)。これはローカルネットワークに公開されることを意味します。

`OLLAMA_NUM_CTX` はモデルとマシンに合わせて設定してください。RAG プロンプト全体がその中に収まらない場合、Ollama はプロンプトを先頭から静かに切り捨て、最初にシステム指示が失われます。

**OpenAI** -- OpenAI のチャット補完 API を呼び出します。`LLM_BACKEND=openai` を設定し、有効な `OPENAI_API_KEY` を提供します。デフォルトでは `gpt-4o-mini` を使用します。`make run-remote` で起動します。より高品質な回答や評価比較に有用です。

Expand Down
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ API Client <--> Query API <--> Ollama / OpenAI / Claude |
- Python 3.12+ (for local development and running tests outside of Docker)
- GNU Make (optional, for convenience targets)

**Hardware (Ollama / local LLM path only):** `make run` pulls `mistral:7b` (~4 GB download) and requires at least **8 GB of free RAM** at runtime (model weights + Docker overhead). On machines with less RAM the Ollama container will be OOM-killed. The remote-LLM path (`make run-remote` with `LLM_BACKEND=claude` or `openai`) has no GPU or RAM requirements beyond the base stack (~2 GB).
**Hardware:** The stack sizes itself to the machine it runs on — container CPU and memory limits, the embedding batch size, and the Ollama context window are all environment variables (see [Configuration](#configuration)), so scale them to the hardware you have. Requirements depend almost entirely on which LLM backend you choose: `make run-remote` with `LLM_BACKEND=claude` or `openai` performs no local inference at all, while the local-LLM path is bounded by the model you select.

One caveat worth knowing before benchmarking locally: **containerised Ollama on macOS and Windows runs on CPU only**, because Docker's Linux VM cannot reach the host GPU. For substantially faster local generation, run Ollama natively on the host and point `OLLAMA_URL` at it — see [LLM Backends](#llm-backends).

## Quick Start

Expand Down Expand Up @@ -64,7 +66,7 @@ make run-remote

On the first run this will pull container images, build the three services, and run database migrations. The schema is applied automatically from `db/migrations/001_initial_schema.sql` (creates the `pgvector` extension, `ingestion_log` and `document_chunks` tables, and the HNSW vector index). To run migrations manually at any time: `make migrate`.

If using Ollama (`make run`), the `mistral:7b` model (~4 GB) is downloaded automatically on first start. Subsequent starts reuse cached layers and volumes.
If using Ollama (`make run`), the model named by `OLLAMA_MODEL` is downloaded automatically on first start. Subsequent starts reuse cached layers and volumes.

4. Verify the services are running:

Expand Down Expand Up @@ -350,7 +352,20 @@ All configuration is driven by environment variables. See `.env.example` for the
| `OPENAI_MODEL` | `gpt-4o-mini` | OpenAI model name |
| `ANTHROPIC_API_KEY` | (empty) | Required when `LLM_BACKEND=claude` |
| `CLAUDE_MODEL` | `claude-opus-4-6` | Claude model name |
| `EMBEDDING_MODEL` | `sentence-transformers/all-MiniLM-L6-v2` | Sentence-transformers model for embedding |
| `EMBEDDING_MODEL` | `nomic-ai/nomic-embed-text-v1.5` | Sentence-transformers model for embedding (768-dim) |

**Performance tuning**

Scale these to the machine you are running on; the defaults are conservative so the stack starts anywhere.

| Variable | Default | Description |
| ----------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `OLLAMA_NUM_CTX` | `8192` | Context window requested from Ollama. The entire RAG prompt must fit or Ollama truncates it from the start, dropping the system prompt. |
| `EMBEDDING_BATCH_SIZE` | `64` | Chunks embedded per batch in the embedding worker. Larger batches raise throughput at the cost of memory. |
| `POSTGRES_SHARED_BUFFERS` | `2GB` | PostgreSQL page cache. Worth raising only once the corpus outgrows it. |
| `POSTGRES_WORK_MEM` | `256MB` | Per-operation sort/hash memory for PostgreSQL. |
| `QUERY_API_CPUS` | `4.0` | CPU limit for the Query API container. Retrieval runs in a thread pool, so this caps concurrent query throughput. |
| `EMBEDDING_WORKER_CPUS` | `12.0` | CPU limit for the embedding worker container. |

**Security & API**

Expand Down Expand Up @@ -389,7 +404,12 @@ All configuration is driven by environment variables. See `.env.example` for the

The Query API supports 3 LLM backends, selectable via the `LLM_BACKEND` environment variable:

**Ollama (default)** -- Runs locally inside the Docker Compose stack. No API key required. The model is pulled automatically on first start. Start with `make run` (or `docker compose --profile local-llm up`). Suitable for development and self-hosted deployments. Requires ~6 GB RAM for the `mistral:7b` model weights (~8 GB total including Docker overhead).
**Ollama (default)** -- Runs locally, with no API key required; the model named by `OLLAMA_MODEL` is pulled automatically on first start. Suitable for development and self-hosted deployments. There are two ways to run it:

- *Containerised* (`make run`, or `docker compose --profile local-llm up`) — zero setup, fully portable. On macOS and Windows this runs inference **on CPU only**: Docker's Linux VM has no access to the host GPU, so generation is slow regardless of how much CPU or memory you give the container.
- *Host-native* — run `ollama serve` on the host so it uses the host GPU (Metal on macOS, CUDA/ROCm on Linux), then start the stack **without** the `local-llm` profile (`make run-remote`) and set `OLLAMA_URL=http://host.docker.internal:11434`. This is typically an order of magnitude faster than the containerised path. Some runtimes (OrbStack) forward `host.docker.internal` to the host loopback, so a server bound to `127.0.0.1` is reachable as-is; on Docker Desktop the native server must listen on all interfaces instead (`OLLAMA_HOST=0.0.0.0:11434`), which does expose it to your local network.

Size `OLLAMA_NUM_CTX` to your model and machine — the whole RAG prompt must fit inside it, or Ollama silently truncates the prompt from the start, discarding the system instructions first.

**OpenAI** -- Calls the OpenAI chat completions API. Set `LLM_BACKEND=openai` and provide a valid `OPENAI_API_KEY`. Uses `gpt-4o-mini` by default. Start with `make run-remote`. Useful for higher-quality answers and evaluation comparisons.

Expand Down
Loading
Loading