人気ブログランキング
人気ブログランキング
Python PR

PythonとStreamlitを活用したドキュメント検索システムの構築方法 (ChatGPT API 不要)

記事内に商品プロモーションを含む場合があります

企業内では、膨大なドキュメントやファイルが生成されますが、それらから必要な情報を効率的に検索するのは困難です。この記事では、PythonとStreamlitを使用して、ChatGPT API を使わずに効率的なドキュメント検索システムを構築する方法について解説します。このシステムは、PDF、Word、Excel、PowerPoint などの複数のファイル形式に対応し、ユーザーの検索クエリに基づいて関連性の高いドキュメントを自動的に抽出します。

システムの概要

システムの特徴

  • ドキュメントの再帰的読み込み
    • 指定されたディレクトリ内の全ての PDF、Word、Excel、PowerPoint ファイルを再帰的に検索し、内容を読み取ります。
  • クエリ検索
    • ユーザーのクエリに基づいて、ドキュメント内のテキストを検索し、関連度の高いドキュメントをリストアップします。
  • TF-IDF とコサイン類似度を使用
    • クエリとドキュメントの類似度を計算し、検索結果をランキング形式で表示します。

必要なツールとセットアップ

1. 必要なライブラリ

以下のライブラリを使用します:

  • streamlit(Web アプリケーション構築)
  • PyMuPDF(PDF ファイルからのテキスト抽出)
  • python-docx(Word ファイルからのテキスト抽出)
  • openpyxl(Excel ファイルからのテキスト抽出)
  • python-pptx(PowerPoint ファイルからのテキスト抽出)
  • scikit-learn(TF-IDF とコサイン類似度計算)

2. ライブラリのインストール

以下のコマンドを実行して必要なライブラリをインストールしてください。

pip install streamlit pymupdf python-docx openpyxl python-pptx scikit-learn

ディレクトリ構成

document_search_app/
│
├── app.py                   # メインアプリケーション
├── requirements.txt         # 必要なライブラリ一覧
└── utils/
    ├── file_loader.py       # ファイル読み込みとテキスト抽出
    └── text_search.py       # 検索アルゴリズム

コード実装

1. ファイル読み込みとテキスト抽出 (file_loader.py)

import os
import fitz  # PyMuPDF for PDF
import docx
import openpyxl
from pptx import Presentation

def extract_text_from_pdf(file_path):
    text = ""
    with fitz.open(file_path) as pdf:
        for page in pdf:
            text += page.get_text()
    return text

def extract_text_from_word(file_path):
    doc = docx.Document(file_path)
    return "\n".join([para.text for para in doc.paragraphs])

def extract_text_from_excel(file_path):
    workbook = openpyxl.load_workbook(file_path)
    text = []
    for sheet in workbook.sheetnames:
        worksheet = workbook[sheet]
        for row in worksheet.iter_rows(values_only=True):
            text.append(" ".join(str(cell) for cell in row if cell))
    return "\n".join(text)

def extract_text_from_powerpoint(file_path):
    presentation = Presentation(file_path)
    text = []
    for slide in presentation.slides:
        for shape in slide.shapes:
            if hasattr(shape, "text"):
                text.append(shape.text)
    return "\n".join(text)

def extract_text(file_path):
    if file_path.lower().endswith('.pdf'):
        return extract_text_from_pdf(file_path)
    elif file_path.lower().endswith('.docx'):
        return extract_text_from_word(file_path)
    elif file_path.lower().endswith('.xlsx'):
        return extract_text_from_excel(file_path)
    elif file_path.lower().endswith('.pptx'):
        return extract_text_from_powerpoint(file_path)
    else:
        return None

def load_documents_from_directory(directory):
    documents = {}
    for root, _, files in os.walk(directory):
        for file in files:
            if file.startswith('~$'):  # 一時ファイルを無視
                continue
            file_path = os.path.join(root, file)
            if file.lower().endswith(('.pdf', '.docx', '.xlsx', '.pptx')):
                try:
                    text = extract_text(file_path)
                    if text:
                        documents[file_path] = text
                except Exception as e:
                    print(f"Error reading {file_path}: {e}")
    return documents

2. 検索アルゴリズム (text_search.py)

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

def search_documents(query, documents):
    doc_texts = list(documents.values())
    file_paths = list(documents.keys())
    
    vectorizer = TfidfVectorizer()
    tfidf_matrix = vectorizer.fit_transform(doc_texts + [query])
    
    query_vector = tfidf_matrix[-1]
    doc_vectors = tfidf_matrix[:-1]
    similarities = cosine_similarity(query_vector, doc_vectors).flatten()
    
    sorted_indices = np.argsort(-similarities)
    results = [(file_paths[i], similarities[i]) for i in sorted_indices if similarities[i] > 0]
    
    return results

3. Streamlit アプリケーション (app.py)

import streamlit as st
from utils.file_loader import load_documents_from_directory
from utils.text_search import search_documents

st.title("ドキュメント検索システム")

# ディレクトリパスの入力
directory = st.text_input("検索対象のディレクトリを入力してください")

if directory:
    if st.button("読み込み"):
        documents = load_documents_from_directory(directory)
        if documents:
            st.success(f"{len(documents)} 件のドキュメントを読み込みました。")
            
            query = st.text_input("検索クエリを入力してください")
            
            if st.button("検索"):
                if query:
                    results = search_documents(query, documents)
                    if results:
                        st.subheader("検索結果")
                        for file_path, score in results:
                            st.write(f"ファイル: {file_path} - 類似度: {score:.2f}")
                    else:
                        st.info("該当する結果が見つかりませんでした。")
        else:
            st.error("ドキュメントが見つかりませんでした。")

システムの動作確認

1. アプリケーションの起動

ターミナルから以下のコマンドを実行してください。

streamlit run app.py

2. アプリケーションの使用方法

  • 検索対象のディレクトリを入力し、「読み込み」ボタンを押すと、指定されたディレクトリ内のドキュメントが読み込まれます。ディレクトリは手入力なので、対象のディレクトリをコピー&ペーストで入力をしてください。
  • 検索クエリを入力し、「検索」ボタンを押すと、クエリに関連するドキュメントが類似度に基づいて表示されます。

まとめ

この記事では、Python と Streamlit を使用して、ChatGPT API を使わずにドキュメント検索システムを構築する方法を紹介しました。今回のシステムは、複数のファイル形式に対応しており、TF-IDF とコサイン類似度を利用して効率的な検索を実現します。

補足記事:Python と Streamlit を活用したドキュメント検索システムの仕組みと類似度の理解 企業や組織では、日々膨大なドキュメントが生成され、それらを効率的に検索して必要な情報に素早くアクセスすることが求められています。そこで...
ABOUT ME
den
完全独学でWEBデザインを無謀にも挑戦している中年男。 工場勤務の会社員で3児の父。 チャレンジを忘れず、妻に怒られても心はおれず。 有益な情報を発信し、これを見ている人の為になればと思っています。
関連記事一覧