import logging import os from pathlib import Path from typing import Any, Dict, List, Tuple from langchain_chroma import Chroma from langchain_core.documents import Document from langchain_core.messages import AIMessage, HumanMessage from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI, OpenAIEmbeddings # Constants EXAMPLE_DIR: Path = Path(__file__).resolve().parent CHROMA_PATH: str = str(EXAMPLE_DIR / "db") OPENAI_AI_MODEL: str = "gpt-4.1-mini" OPENAI_API_KEY: str | None = os.getenv("OPENAI_API_KEY") OPENAI_AI_EMBEDDING_MODEL: str = "text-embedding-3-large" # Initialize embeddings and load the Chroma database embeddings: OpenAIEmbeddings = OpenAIEmbeddings( model=OPENAI_AI_EMBEDDING_MODEL, openai_api_key=OPENAI_API_KEY ) db_chroma: Chroma = Chroma( collection_name="rag_collection", persist_directory=CHROMA_PATH, embedding_function=embeddings, ) # Prompt template for generating answers PROMPT_TEMPLATE: str = """ Answer the question based only on the following context: {context} Answer the question based on the above context: {question}. Provide a detailed answer. Don't justify your answers. Don't give information not mentioned in the CONTEXT INFORMATION. Do not say "according to the context" or "mentioned in the context" or similar. """ def call_api( prompt: str, options: Dict[str, Any], context: Dict[str, Any] ) -> Dict[str, str]: """ Process a prompt using RAG and return the response. Args: prompt: The user's question or prompt options: Configuration options including topK context: Additional context for the request Returns: Dict containing the model's response Raises: Exception: If there's an error during processing """ try: k: int = options.get("config", {}).get("topK", 5) docs_chroma: List[Tuple[Document, float]] = ( db_chroma.similarity_search_with_score( prompt, k=k, ) ) context_text: str = "\n\n".join( [doc.page_content for doc, _score in docs_chroma] ) # Generate prompt using the template prompt_template: ChatPromptTemplate = ChatPromptTemplate.from_template( PROMPT_TEMPLATE ) final_prompt: str = prompt_template.format( context=context_text, question=prompt ) # Fetch from OpenAI API chat: ChatOpenAI = ChatOpenAI( model_name=OPENAI_AI_MODEL, temperature=0, openai_api_key=OPENAI_API_KEY ) message: HumanMessage = HumanMessage(content=final_prompt) response: AIMessage = chat.invoke([message]) result: Dict[str, str] = { "output": response.content, } return result except Exception as e: logging.error(f"Error in call_api: {str(e)}") raise