全体像
ローカルLLM(Ollama)と RAG(PDF→ベクトル検索)を組み合わせ、厚労省資料に基づく回答を返すプロトタイプです。
フロント(GitHub Pages)からは、HTTPS で公開した API(FastAPI)に対して /chat を呼び出します。
バックエンド(API)
Python: 3.10+(推奨: 3.13)FastAPI: HTTP API(GET /status,POST /chatなど)uvicorn: ASGI サーバー(開発は--reload)CORS: GitHub Pages からのアクセスを許可(現状はallow_origins=["*"])
補足: ブラウザ上で blocked by CORS policy と表示されても、実際には API 側が 500 を返している(またはトンネル先が落ちている)だけのことがあります。
まず GET /health → GET /status → GET /sources の順で 200 が返るかを確認してください(UIは起動時に /sources を呼びます)。
APIバージョン: 0.2.0
API の主なエンドポイント: /health, /status, /diagnostics, /sources, /reload,
/search, /generate, /chat
LLM / 埋め込み(ローカル推論)
Ollama: ローカルLLM実行基盤(文章生成と埋め込みの両方)- 生成モデル(例):
gemma2:2b,gemma2,llama3.1 - 埋め込みモデル:
nomic-embed-text
初回の遅さ対策として、API起動時に埋め込み処理を軽くウォームアップします(失敗しても API は落としません)。
RAG(PDF取り込み・検索)
LangChain: PDF読み込み/分割、ベクトル検索の統合PyPDFLoader: PDF→テキスト抽出(標準フォールバック)PyMuPDFLoader(任意): PDF→テキスト抽出(段組/レイアウトで有利な場合あり、環境変数PDF_LOADER=pymupdf)RecursiveCharacterTextSplitter: チャンク分割-
ChromaDB: ベクトルDB(永続化ディレクトリ: 既定./chroma_db/ 書き込み不可の場合はユーザー領域へフォールバック。 安全のため自動削除/置換対象はchroma_db*のみに限定) rag_filter: 検索結果にキーワードフィルタをかけ、全落ち時はフォールバックで検索結果をそのまま使用(API・Streamlit・CLIで共通)
PDFは ./pdfs(環境変数 PDF_DIR)に配置します。追加/更新後は POST /reload で索引(検索の準備)を作り直して反映できます。
スキャンPDFでテキスト抽出できない場合は「要OCR」として案内されます。必要なら ocrmypdf による自動OCRも可能です(環境変数 OCR_MODE=auto / OCR_LANG など。macOS例: brew install ocrmypdf tesseract)。
チャンク分割は CHUNK_SIZE / CHUNK_OVERLAP で調整できます。
フロントエンド(GitHub Pages)
docs/index.html+docs/app.js+docs/style.css: 静的チャットUI- ブラウザから
POST /chatを呼び出し、根拠(参照ページ)や処理時間(内訳)を表示 - APIのURLは
localStorageまたは?api=...で指定 - 送信中の多重実行防止、再送、入力履歴、Markdown表示、エラー要点+詳細ログ(折りたたみ)を実装
- 回答は参照PDF(資料)に書かれている内容に限定し、該当箇所を特定できない場合は「資料にない」と返します
公開/運用(例)
cloudflared: ローカルAPIを HTTPS で公開(GitHub Pages から混在コンテンツにならないようにする)launchd(macOS): uvicorn をログイン/再起動後に自動起動(テンプレ:launchd/com.vaccine.api.plist)
クイックトンネル(Quick Tunnel)はURLが変わるため、常時稼働は固定トンネル(named tunnel)が推奨です(README参照)。
主要ライブラリ(requirements.txt)
ollama==0.6.1langchain-community==0.4.1langchain-text-splitters==1.1.0chromadb==1.4.1pypdf==6.6.2pymupdf(任意):PyMuPDFLoaderを使う場合fastapi==0.117.1uvicorn[standard]==0.40.0streamlit==1.53.1(別UI/デモ用)