🙆

【個人開発】NotionもDBも一元管理!GPT-4×FastAPIで作る「ドキュメント管理AI」の裏側

に公開

はじめに

エンジニアの皆さんは 「ドキュメントが散らばりすぎて探せない問題」 に悩まされていませんか?

・仕様書は Notionにある
・技術メモはローカルの Markdownにある
・実際のデータは PostgreSQLに入っている
・顧客データは CSVで管理している

これらを横断して検索し、分析までしてくれるAIアシスタントがいれば便利だと思い、 「Tech Doc Assistant」 というアプリを開発しました。

今回は、 FastAPI+LangChain+GPT-4 を用いて、複数のデータソース(Notion,DB,Markdown)を統合的に扱うRAG(Retrieval Augmented Generation)システムを構築した際の技術的な知見を共有します。

開発したアプリ:Tech Doc Assistant

デモサイト: https://tech-doc-assistant.vercel.app

主な機能

  1. Markdownドキュメント管理: 基本的なドキュメント管理機能
  2. Notion連携: Notionのページを自動で取り込み、検索対象にする
  3. 高度なAI検索 (RAG): 単なるキーワード検索ではなく、文脈を理解した回答
  4. データ分析: DBやCSVからデータを読み込み、Pandas/AIで分析・可視化
  5. チャンク分析: 長文ドキュメントを意味のまとまりで分割し、検索精度を向上

スクリーンショット 2026-01-04 161524.png

技術スタックとアーキテクチャ

開発効率とパフォーマンスを両立させるため、以下の構築を採用しました。特にバックエンドはPythonの豊富なAIエコシステムを活用するためにFastAPIを選択しています。

Backend(Pyhton)

Framework:FastAPI(非同期処理と型安全性)
LLM Orchestration:LangChain,LangGraph
Vector DB:Pinecone(高速なベクトル検索)
Data Analysis:Pandas,Numpy,Plotly(データ処理と可視化)
Database:PostgreSQL(psycopg2-binary,SQLAlchemy)
External API:Notion Client

Frontend

Framework:Next.js(App Router)
Platform:Vercel

Infrastructure/CI/CD

CI/CD:Github Action
Environment:Docker(開発環境)

実装ポイント

バックエンドのディレクトリ構造は、「機能(Service)」ごとに責務を明確に分離しました。これにより、RAGのロジックや外部連携の改修が容易になっています。

backend/
├── main.py            # エントリーポイント
├── models.py          # Pydantic/DBモデル
├── services/          # ビジネスロジックの中核
│   ├── chunking.py        # テキスト分割ロジック
│   ├── notion_service.py  # Notion連携
│   ├── data_analysis.py   # データ分析・可視化
│   ├── qa.py              # 質問応答(RAG)
│   ├── search.py          # ベクトル検索
│   └── database_connector.py
└── tests/             # Pytestによるテスト

特に工夫した3つの技術ポイントを紹介します。

1. RAGの精度を高める「チャンク分析」

RAGにおいて最も重要なのは 「ドキュメントをどう分割(Chunking)するか」 です。単に文字数で区切るだけでは、文脈が分断され、AIが正しく回答できません。

今回はlangchain-text-splittersを活用しつつ、Markdownのヘッダー構造を意識した分割処理を実装しました。

from langchain_text_splitters import MarkdownHeaderTextSplitter, RecursiveCharacterTextSplitter

def intelligent_chunking(text: str):
    # Markdownのヘッダーベースで分割し、コンテキストを保持
    headers_to_split_on = [
        ("#", "Header 1"),
        ("##", "Header 2"),
        ("###", "Header 3"),
    ]
    markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
    md_header_splits = markdown_splitter.split_text(text)

    # さらにトークン数で微調整する処理を追加
    # ... (RecursiveCharacterTextSplitterなどで再分割)
    
    return chunks

これにより、「どのセクションに書かれている情報か」というメタデータを保持したままベクトル化できるため、検索精度が大幅に向上しました。

2. Notion APIとの連携

ドキュメントの多くはNotionにあるため、notion-clientを使用して同期機能を実装しました。Notionデータは「ブロック」という単位で管理されており、そのままではLLMに扱いにくいため、以下のような変換パイプラインを構築しました。

  1. Notion APIでページ内の全ブロックを取得
  2. ブロックタイプ(Paragraph,Heading,Codeなど)に応じてMarkdownテキストに変換
  3. 変換したテキストを前述のchunking.pyに渡してベクトル化

3. 自然言語によるデータ分析

「先月の売上推移はどうだった?」といった質問に対し、テキストで返すだけでなく、グラフで可視化する機能を実装しました。

ユーザーの自然言語クエリを、LangChainを用いてPandasのクエリ(またはSQL)に変換し、実行結果をPlotlyのグラフオブジェクトとして生成しています。

import pandas as pd
import plotly.express as px

def analyze_data_and_plot(df: pd.DataFrame, query: str):
    # LLMがデータフレームのカラム構造を理解し、
    # 適切な分析コードを生成・実行するフロー
    # ...
    
    # Plotlyで可視化
    fig = px.bar(df, x='date', y='sales', title='Monthly Sales')
    return fig.to_json()

開発での苦労と解決策

依存ライブラリの管理

langchain,numpy,pandas,pydanticなど、依存関係が複雑になりがちなライブラリを多数使用しています。特に、pydanticのv1/v2の互換性や、numpyのバージョン依存には注意が必要でした。requirements.txtを細かく管理し、Docker環境でビルドを安定させることに注力しました。

レスポンス速度の課題

これに対しては以下の対策を行いました。
・ FastAPIのasync/awaitを徹底する
・ Pineconeへのクエリを並列化する
・ フロントエンドではストリーミングレスポンスを活用する

まとめ・今後の展望

FastAPIとLangChainを組み合わせることで、「ドキュメント管理」×「データ分析」 という2つの領域を統合したアプリを個人開発レベルでも構築できました。

今後は以下の機能拡張を考えています。

  • Slack/Teams連携 :チャットツールから直接botに質問
  • ローカルLLM対応 :機密性の高いデータ向けにOllamaなどでローカルモデルを選択可能に
  • マルチモーダル対応 :図表や画像を含めたドキュメント理解

もし「RAGアプリを作りたい」「ドキュメント管理に役立てたい」という方がいれば、ぜひ参考にしてみてください!

参考リンク

FastAPI 公式ドキュメント
LangChain 公式ドキュメント

Discussion