mcpField
D
document-chat-interface

document-chat-interface

github.com/qodex-ai開発47146 回インストール42 週間前に更新
リポジトリ

document-chat-interface について

自然言語で文書を検索・質問できる会話型インターフェースの開発ガイドです。文書の取り込み、検索、会話コンテキスト、引用を扱い、LangChain、LlamaIndex、RAGの実装例を紹介します。

主な機能

  1. 01PDF、リポジトリ、メール、ウェブページの処理
  2. 02テキストの抽出、整形、分割、メタデータ付与
  3. 03会話コンテキストの維持
  4. 04出典を示した回答の生成
  5. 05質問の明確化と追加質問への対応

活用シーン

  1. 01レポートや研究論文の質問応答を構築
  2. 02メールアーカイブの会話型検索
  3. 03質問を通じたコードリポジトリの調査
  4. 04社内文書のインタラクティブな参照環境の構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/qodex-ai/ai-agent-skills --skill document-chat-interface

インストール後、Claude Code で/document-chat-interfaceを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

examples/
conversation_manager.py
document_processors.py
text_processor.py

詳細

ドキュメントチャットインターフェース

自然言語を使ってユーザーがドキュメントに質問したり、やり取りしたりできる、インテリジェントなチャットインターフェースを構築します。静的なドキュメントを、対話可能なナレッジソースに変換できます。

概要

ドキュメントチャットインターフェースは、次の3つの機能を組み合わせたものです。

  1. ドキュメント処理 - ドキュメントを抽出して準備します
  2. 意味理解 - 質問を理解し、関連するコンテンツを見つけます
  3. 会話型インターフェース - コンテキストを維持し、自然な応答を返します
主な用途
  • PDF の質疑応答:研究論文、レポート、書籍に関する質問に回答します
  • メール検索:メールアーカイブから会話形式で情報を見つけます
  • GitHub エクスプローラー:コードリポジトリについて質問します
  • ナレッジベース:社内ドキュメントに対話形式でアクセスします
  • 契約書レビュー:自然言語で法的文書に質問します
  • リサーチアシスタント:学術論文を対話形式で調べます

アーキテクチャ

Document Source
    ↓
Document Processor
    ├→ Extract text
    ├→ Process content
    └→ Generate embeddings
    ↓
Vector Database
    ↓
Chat Interface ← User Question
    ├→ Retrieve relevant content
    ├→ Maintain conversation history
    └→ Generate response

主なコンポーネント

1. ドキュメントソース

実装例については、examples/document_processors.py を参照してください。

PDF ドキュメント
  • PDF ページからテキストを抽出します
  • ドキュメントの構造とメタデータを保持します
  • OCR(pytesseract)を使用してスキャンされた PDF を処理します
  • 表を抽出します(pdfplumber)
GitHub リポジトリ
  • リポジトリからコードファイルを抽出します
  • リポジトリの構造を解析します
  • 複数のファイル形式を処理します
メールアーカイブ
  • メールのメタデータ(差出人、宛先、件名、日付)を抽出します
  • メール本文の内容を解析します
  • 複数のメールボックス形式に対応します
ウェブページ
  • ページのテキストと構造を抽出します
  • 見出しの階層を保持します
  • リンクとナビゲーションを抽出します
YouTube/音声
  • YouTube 動画からトランスクリプトを取得します
  • 音声ファイルを文字起こしします
  • 複数の形式に対応します
2. ドキュメント処理

実装例については、examples/text_processor.py を参照してください。

テキストの抽出とクリーニング
  • 余分な空白や特殊文字を削除します
  • 重複部分を含むスマートなテキスト分割を行います
  • 文の境界をインテリジェントに検出します
メタデータの抽出
  • タイトル、著者、日付、言語を抽出します
  • 単語数とドキュメント統計を計算します
  • ドキュメントのソースと形式を記録します
構造の保持
  • 分割したテキスト内で見出しの階層を保持します
  • セクションのコンテキストを維持します
  • 階層的な検索を可能にします
3. チャットインターフェースの設計

実装例については、examples/conversation_manager.py を参照してください。

会話の管理
  • サイズ制限を設けて会話履歴を維持します
  • メッセージのメタデータ(タイムスタンプ、ロール)を記録します
  • LLM 連携に必要なコンテキストを提供します
  • 必要に応じて履歴を消去します
質問の調整
  • 質問に含まれる暗黙的な参照を補足します
  • 代名詞やコンテキストへの参照を処理します
  • 以前のコンテキストを使って質問を明確にします
応答の生成
  • 回答にドキュメントのコンテキストを使用します
  • プロンプト内で会話履歴を維持します
  • 出典を提示します
  • 対象範囲外の質問に対応します
4. ユーザーエクスペリエンス機能
引用と出典
def format_response_with_citations(response: str, sources: List[Dict]) -> str:
    """Add source citations to response"""

    formatted = response + "\n\n**Sources:**\n"
    for i, source in enumerate(sources, 1):
        formatted += f"[{i}] Page {source['page']} of {source['source']}\n"
        if 'excerpt' in source:
            formatted += f"    \"{source['excerpt'][:100]}...\"\n"

    return formatted
確認の質問
def generate_follow_up_questions(context: str, response: str) -> List[str]:
    """Suggest follow-up questions to user"""

    prompt = f"""
    Based on this Q&A, generate 3 relevant follow-up questions:
    Context: {context[:500]}
    Response: {response[:500]}
    """

    follow_ups = llm.generate(prompt)
    return follow_ups
エラー処理
def handle_query_failure(question: str, error: Exception) -> str:
    """Handle when no relevant documents found"""

    if isinstance(error, NoRelevantDocuments):
        return (
            "I couldn't find information about that in the documents. "
            "Try asking about different topics like: "
            + ", ".join(get_main_topics())
        )
    elif isinstance(error, ContextTooLarge):
        return (
            "The answer requires too much context. "
            "Can you be more specific about what you'd like to know?"
        )
    else:
        return f"I encountered an issue: {str(error)[:100]}"

実装フレームワーク

LangChain を使用する
from langchain.document_loaders import PDFLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationalRetrievalChain

# Load document
loader = PDFLoader("document.pdf")
documents = loader.load()

# Split into chunks
splitter = CharacterTextSplitter(chunk_size=1000)
chunks = splitter.split_documents(documents)

# Create embeddings
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(chunks, embeddings)

# Create chat chain
llm = ChatOpenAI(model="gpt-4")
qa = ConversationalRetrievalChain.from_llm(
    llm=llm,
    retriever=vectorstore.as_retriever(),
    return_source_documents=True
)

# Chat interface
chat_history = []
while True:
    question = input("You: ")
    result = qa({"question": question, "chat_history": chat_history})
    print(f"Assistant: {result['answer']}")
    chat_history.append((question, result['answer']))
LlamaIndex を使用する
from llama_index import GPTVectorStoreIndex, SimpleDirectoryReader, ChatMemoryBuffer
from llama_index.llms import ChatMessage, MessageRole

# Load documents
documents = SimpleDirectoryReader("./docs").load_data()

# Create index
index = GPTVectorStoreIndex.from_documents(documents)

# Create chat engine with memory
chat_engine = index.as_chat_engine(
    memory=ChatMemoryBuffer.from_defaults(token_limit=3900),
    llm="gpt-4"
)

# Chat loop
while True:
    question = input("You: ")
    response = chat_engine.chat(question)
    print(f"Assistant: {response}")
RAG ベースのアプローチを使用する
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np

# Load and embed documents
model = SentenceTransformer('all-MiniLM-L6-v2')
documents = load_documents("document.pdf")
embeddings = model.encode(documents)

# Create FAISS index
dimension = embeddings.shape[1]
index = faiss.IndexFlatL2(dimension)
index.add(np.array(embeddings).astype('float32'))

# Chat function
def chat(question):
    # Embed question
    q_embedding = model.encode(question)

    # Retrieve documents
    k = 5
    distances, indices = index.search(
        np.array([q_embedding]).astype('float32'), k
    )

    # Get relevant documents
    context = " ".join([documents[i] for i in indices[0]])

    # Generate response
    response = llm.generate(
        f"Context: {context}\nQuestion: {question}\nAnswer:"
    )
    return response

ベストプラクティス

ドキュメントの処理
  • ✓ 複数の形式に対応します(PDF、TXT、docx など)
  • ✓ 大きなドキュメントを効率的に処理します
  • ✓ ドキュメントの構造を保持します
  • ✓ メタデータを抽出します
  • ✓ 複数の言語に対応します
  • ✓ スキャンされた PDF 向けに OCR を実装します
会話の品質
  • ✓ 会話のコンテキストを維持します
  • ✓ 確認の質問をします
  • ✓ 出典を引用します
  • ✓ 曖昧さに対応します
  • ✓ 追加の質問を提案します
  • ✓ 対象範囲外の質問に対応します
パフォーマンス
  • ✓ 検索速度を最適化します
  • ✓ キャッシュを実装します
  • ✓ 大規模なドキュメントセットを処理します
  • ✓ ドキュメントをバッチ処理します
  • ✓ レイテンシを監視します
  • ✓ ページネーションを実装します
ユーザーエクスペリエンス
  • ✓ 応答を分かりやすく整形します
  • ✓ 出典を引用できるようにします
  • ✓ ドキュメントブラウザー/エクスプローラーを用意します
  • ✓ 検索候補を表示します
  • ✓ クエリ履歴を表示します
  • ✓ 会話をエクスポートできるようにします

よくある課題と解決策

課題:無関係な回答

解決策:

  • 検索を改善する(コンテキストを増やす、より優れた埋め込みを使用する)
  • 回答をコンテキストと照合する
  • 明確化の質問をする
  • 信頼度スコアリングを実装する
  • ハイブリッド検索を使用する
課題:ターンをまたいだコンテキストの喪失

解決策:

  • 会話のメモリを保持する
  • 履歴に基づいて検索を更新する
  • 長い会話を要約する
  • 過去のクエリの重みを再調整する
課題:長いドキュメントの処理

解決策:

  • 階層的なチャンク分割
  • まず要約する
  • 質問を洗練する
  • マルチホップ検索
  • ドキュメントのナビゲーション
課題:コンテキストウィンドウの制限

解決策:

  • 検索したコンテキストを圧縮する
  • ドキュメントの要約を使用する
  • 階層的な検索
  • 最も関連性の高いセクションに絞る
  • 反復的に洗練する

高度な機能

複数ドキュメントの分析
def compare_documents(question: str, documents: List[str]):
    """Analyze and compare across multiple documents"""
    results = []

    for doc in documents:
        response = query_document(doc, question)
        results.append({
            "document": doc.name,
            "answer": response
        })

    # Compare and synthesize
    comparison = llm.generate(
        f"Compare these answers: {results}"
    )
    return comparison
インタラクティブなドキュメント探索
class DocumentExplorer:
    def __init__(self, documents):
        self.documents = documents

    def browse_by_topic(self, topic):
        """Find documents by topic"""
        pass

    def get_related_documents(self, doc_id):
        """Find similar documents"""
        pass

    def get_key_terms(self, document):
        """Extract key terms and concepts"""
        pass

リソース

ドキュメント処理ライブラリ
  • PyPDF:PDF の処理
  • python-docx:Word ドキュメントの処理
  • BeautifulSoup:ウェブスクレイピング
  • youtube-transcript-api:YouTube の文字起こし
チャットフレームワーク
  • LangChain:包括的なフレームワーク
  • LlamaIndex:ドキュメントに特化
  • RAG ライブラリ:ベクトル DB との統合

実装チェックリスト

  • サポートするドキュメントソースを選択する
  • ドキュメントの読み込みと処理を実装する
  • ベクトルデータベース/埋め込みをセットアップする
  • チャットインターフェースを構築する
  • 会話管理を実装する
  • ソースの引用を追加する
  • エッジケース(大きなドキュメント、OCR など)に対応する
  • エラー処理を実装する
  • パフォーマンス監視を追加する
  • 実際のドキュメントでテストする
  • デプロイして監視する

はじめに

  1. シンプルに始める:単一の PDF、基本的なチャット
  2. 機能を追加する:複数ドキュメント、会話履歴
  3. 品質を向上させる:より優れたチャンク分割と検索
  4. スケールする:より多くの形式と、より大きなドキュメントをサポートする
  5. 仕上げる:UX の改善、エラー処理

コメント