Source code for aidputils.agents.tools.rag

import oci
import json

from aidputils.agents.auth.util import auth_utils
from aidputils.agents.tools.base_tool import BaseTool
from aidputils.agents.tools.ragtool.helpers.vector_search import execute_vector_search
from aidputils.agents.tools.ragtool.helpers.wallet_utils import create_wallet_from_credentials
from aidputils.agents.tools.service.kb_service import KBService
from aidputils.agents.tools.service.genai_service import GenAIService
from aidputils.agents.toolkit.metrics_util import MetricUtility
from aidputils.agents.auth.signer.custom_remote_signer import CustomRemoteSigner
from aidputils.agents.toolkit import chat_context

import logging

from aidputils.agents.tools.utils import SystemUtils

logger = logging.getLogger(__name__)


[docs] @BaseTool.register class RAGTool(BaseTool): metricsUtil = MetricUtility("RAG_TOOL") success_counter = metricsUtil.create_counter("RAG_TOOL_SUCCESS_COUNTER") failure_counter = metricsUtil.create_counter("RAG_TOOL_FAILURE_COUNTER") @classmethod def _invoke_tool(cls, conf, runtime_params, **context_vars): is_success = False try: tool_name = chat_context.tool_context_var.get() cls.logger().info(f"context variable for tool name {tool_name}") catalog = conf['catalog'] schema = conf['schema'] kb_name = conf['knowledgeBase'] query = runtime_params['query'] cls.logger(tool_name="agent-app-rag").info(f"Invoking rag tool for {query}") top_k = conf.get('top_k', conf.get('topK')) if top_k is None: # If not found in conf, try runtime_params with both spellings top_k = runtime_params.get('top_k', runtime_params.get('topK')) if not catalog or not schema or not kb_name: cls.logger().error("Catalog / schema / kb is not configured") return { "result": { "content": [ { "type": "text", "text": "RAG Tool is configured incorrectly" } ], "isError": True } } if not query or top_k is None: return { "result": { "content": [ { "type": "text", "text": "Missing parameters. One of query or top_k is not provided" } ], "isError": True } } # 1. Fetch Knowledge Base and Credentials datalakeId = context_vars.get("datalake_id") or SystemUtils.get_env_var("DATALAKE_ID") lakeproxy_endpoint = auth_utils.get_lakeproxy_endpoint(datalakeId) context_vars.setdefault("service_endpoint", lakeproxy_endpoint) context_vars.setdefault("signer", oci.auth.signers.get_resource_principals_signer()) cls.logger().info("Starting tool invocation for knowledge base: %s, hitting endpoint %s", kb_name, lakeproxy_endpoint) cls.logger().info("Initializing KBService") kb_service = KBService(conf, **context_vars) cls.logger().debug(f"KBService initialized: {kb_service}") cls.logger().info("Fetching knowledge base: catalog=%s, schema=%s, kb_name=%s", catalog, schema, kb_name) kb = kb_service.fetch_knowledge_base(catalog, schema, kb_name) cls.logger().debug(f"KB fetched: {kb}") cls.logger().info("Fetching vector search credentials") credentials = kb_service.fetch_vector_credentials(catalog, schema, kb_name) cls.logger().debug(f"credentials fetched: {credentials}") # 2. Prepare Wallet db_user = credentials.data.user db_password = credentials.data.password tns_alias = credentials.data.tns_alias wallet_password = credentials.data.wallet_password wallet_path = create_wallet_from_credentials(credentials) cls.logger().info("Finding Oracle Cloud region by wallet") genai_service_endpoint = conf.get("llm", {}).get("endpoint") cls.logger().debug( f"service_endpoint: {genai_service_endpoint}") embedding_model_name = kb.data.embedding_model_name vector_embedded_table = kb.data.vector_table embedding_model_type = kb.data.embedding_model_source_type # 4. Instantiate GenAI service cls.logger().info("Instantiating GenAIService for endpoint: %s", genai_service_endpoint) gen_ai_signer = CustomRemoteSigner() genai_service = GenAIService(conf, signer=gen_ai_signer, service_endpoint=genai_service_endpoint) # 5. Run Vector Search cls.logger().info("Executing vector search for query: '%s'", query) result_list = execute_vector_search( db_user=db_user, db_password=db_password, dsn=tns_alias, wallet_password = wallet_password, wallet_path=wallet_path, model_type=embedding_model_type, model_name=embedding_model_name, vector_table=vector_embedded_table, query=query, top_k=top_k, genai_service=genai_service ) cls.logger().info("Vector search returned %d results", len(result_list) if result_list else 0) # 6. Generate LLM Response cls.logger().info("Generating LLM response") llm_result = genai_service.generate_response(conf, runtime_params=runtime_params, result_list=result_list) cls.logger().info("Tool invocation completed successfully") cls.logger(tool_name="agent-app-rag").info(f"Response from rag tool {llm_result}") is_success = True return llm_result except Exception as e: cls.logger().exception("Exception during tool invocation", exc_info=True) is_success = False return {"error": f"An error occurred during RAG Tool invocation: {str(e)}"} finally: if is_success: cls.metricsUtil.increment_counter(cls.success_counter) else: cls.metricsUtil.increment_counter(cls.failure_counter) @classmethod def _format_output_as_mcp(cls, response: dict) -> dict: if "error" in response: return { "result": { "content": [ { "type": "text", "text": response["error"] } ], "isError": True } } # Prepare the MCP structured output structured_result = { "answer": response.get("answer", ""), "retrieved_chunks": response.get("retrieved_chunks", []) } text_output = json.dumps(structured_result, ensure_ascii=False, separators=(",", ":")) return { "result": { "content": [ { "type": "text", "text": text_output } ], "structuredContent": structured_result } }