query.py
1 #!/usr/bin/env python3 2 """Simple script to query the vector database with a question.""" 3 4 import argparse 5 import logging 6 import sys 7 8 from src import Config 9 from src.cli.constants import ( 10 EXIT_CODE_ERROR, 11 SEPARATOR_CHAR, 12 SEPARATOR_LENGTH, 13 ) 14 from src.components import execute_query, initialize_rag_components 15 from src.logger import Logger 16 from src.pipeline import PipelineStatus, QueryContext 17 18 19 def _log_query_info( 20 query: str, 21 user_role: str | None, 22 role_mapping: dict[str, list[str]], 23 logger: logging.Logger 24 ) -> None: 25 """Log query information and role mapping.""" 26 logger.info(SEPARATOR_CHAR * SEPARATOR_LENGTH) 27 logger.info("Querying Vector Database") 28 logger.info(SEPARATOR_CHAR * SEPARATOR_LENGTH) 29 logger.info(f"Query: {query}") 30 if user_role: 31 logger.info(f"User role: {user_role}") 32 if role_mapping: 33 logger.info(f"Role mapping loaded: {len(role_mapping)} roles") 34 if user_role and user_role in role_mapping: 35 logger.info(f"Role '{user_role}' maps to tags: {role_mapping[user_role]}") 36 logger.info("") 37 38 39 def _display_results( 40 context: QueryContext, 41 logger: logging.Logger, 42 ) -> None: 43 """Display query results, citations, and retrieved documents.""" 44 logger.info("\n" + SEPARATOR_CHAR * SEPARATOR_LENGTH) 45 logger.info("Final Answer") 46 logger.info(SEPARATOR_CHAR * SEPARATOR_LENGTH) 47 logger.info(context.llm_response or "(no response)") 48 49 if context.citations: 50 logger.info("\nSources:") 51 for c in context.citations: 52 cid = c.get("id") 53 source = c.get("source") 54 score = c.get("score") 55 logger.info(f" [{cid}] {source} score={score}") 56 57 def main(): 58 """Query the vector database with a question from command line arguments.""" 59 parser = argparse.ArgumentParser( 60 description="Query vector database with role-aware access control from config" 61 ) 62 parser.add_argument( 63 "query", 64 nargs="+", 65 help="Search query string", 66 ) 67 args = parser.parse_args() 68 69 config = Config.get_config() 70 71 Logger.setup(config) 72 logger = logging.getLogger(__name__) 73 74 query = " ".join(args.query) 75 76 user_role = config.access_control.default_user_role 77 role_mapping = config.access_control.get_role_mapping() 78 79 _log_query_info(query, user_role, role_mapping, logger) 80 81 try: 82 components = initialize_rag_components() 83 84 context = execute_query( 85 components, 86 query, 87 user_role=user_role, 88 role_mapping=role_mapping, 89 ) 90 91 if context.status == PipelineStatus.FAILED: 92 raise RuntimeError(f"Pipeline failed: {context.error}") 93 94 _display_results(context, logger) 95 96 except Exception as e: 97 logger.error(f"✗ Error: {e}", exc_info=True) 98 sys.exit(EXIT_CODE_ERROR) 99 100 if __name__ == "__main__": 101 main()