""" ベクトルストア構築ユーティリティ """ import logging import os from typing import List, Optional from dotenv import load_dotenv from langchain_chroma import Chroma from langchain_core.documents import Document from langchain_openai import OpenAIEmbeddings from .embedding_storage import save_embeddings from .loader import load_chunks_from_json, display_document_info logger = logging.getLogger(__name__) # .envファイルからAPIキーを読み込む load_dotenv(dotenv_path=".env") def build_vector_store( docs_path: str = 'data/processed/chunks.json', persist_dir: str = 'data/vector_store', model_name: str = 'text-embedding-3-small', save_embeddings_to_file: bool = True, embeddings_dir: str = 'data/embeddings' ) -> None: """ ドキュメントチャンクからベクトルストアを構築し、必要に応じて埋め込みも保存する Args: docs_path: ドキュメントチャンクが格納されたJSONファイルのパス persist_dir: ベクトルストアを保存するディレクトリ model_name: 使用するOpenAI埋め込みモデル名 save_embeddings_to_file: 埋め込みを別ファイルに保存するかどうか embeddings_dir: 埋め込みを保存するディレクトリ """ logger.debug("OPENAI_API_KEY set: %s", bool(os.getenv("OPENAI_API_KEY"))) logger.info("全てのインポートが成功しました") # チャンクJSONからドキュメントを読み込む docs_list = load_chunks_from_json(docs_path) # ドキュメント情報を表示 display_document_info(docs_list) # OpenAI埋め込みを初期化 embeddings = OpenAIEmbeddings(model=model_name) logger.info(f"埋め込みモデル初期化済み: {model_name}") # ドキュメントが存在する場合のみベクトルストアを作成 if docs_list: # 全ドキュメントの埋め込みを生成 texts = [doc.page_content for doc in docs_list] logger.info(f"{len(texts)}件のドキュメントに対して埋め込みを生成中...") vectors = embeddings.embed_documents(texts) # 埋め込みをファイルに保存する場合 if save_embeddings_to_file: embeddings_file = save_embeddings( documents=docs_list, vectors=vectors, model_name=model_name, embeddings_dir=embeddings_dir ) logger.info(f"埋め込みを保存しました: {embeddings_file}") # 生成した埋め込みでChromaベクトルストアを作成 # Chromaは内部でストレージを管理するためfrom_documentsを利用 db = Chroma.from_documents(docs_list, embeddings, persist_directory=persist_dir) logger.info(f"ベクトルストアを作成し保存しました: {persist_dir}") logger.info(f"{len(docs_list)}件のドキュメントチャンクをインデックス化しました") else: logger.error("インデックス化するドキュメントがありません。chunks.jsonファイルを確認してください。") raise ValueError("入力ファイルにドキュメントが見つかりません") def search_vector_store( query: str, persist_dir: str = 'data/vector_store', k: int = 5, model_name: str = 'text-embedding-3-small' ) -> List[Document]: """ ベクトルストアから関連ドキュメントを検索する Args: query: 検索クエリ persist_dir: ベクトルストアが保存されているディレクトリ k: 取得するドキュメント数 model_name: 使用するOpenAI埋め込みモデル名 Returns: 関連ドキュメントのリスト """ # OpenAI埋め込みを初期化 embeddings = OpenAIEmbeddings(model=model_name) # 保存済みベクトルストアを読み込む db = Chroma(persist_directory=persist_dir, embedding_function=embeddings) # レトリーバーを作成 retriever = db.as_retriever( search_type='similarity', search_kwargs={'k': k} ) # 関連ドキュメントを取得 docs = retriever.invoke(query) return docs