Lazy initialization separates quick object creation from expensive resource setup. In a RAG service, loading a vector index and establishing model connections can take time or fail, so an instance can be created before those resources are ready. section 12.3
Start with unset resource fields and an initialized flag. An asynchronous initialization method then creates embeddings, loads the FAISS index, builds a retriever, and configures the language model. Query handlers check the flag and return an error rather than using an unready service. A Chainlit chat can await initialization when the session starts. section 12.3
Listing 12.13 DakkaBotCore async initialization of RAG components
class DakkaBotCore: #1
def __init__(self):
self.retriever = None #2
self.llm = None
self.vector_store = None
self.initialized = False #3
async def initialize(self): #4
try:
embeddings = GeminiEmbeddings() #5
self.vector_store = FAISS.load_local(
"DATA/faiss_index",
embeddings=embeddings,
allow_dangerous_deserialization=True
)
self.retriever = self.vector_store.as_retriever(
search_kwargs={"k": 5} #6
)
self.llm = ChatGoogleGenerativeAI(
model="gemini-2.5-flash", #7
temperature=0.0,
google_api_key=os.environ["GEMINI_API_KEY"],
convert_system_message_to_human=True
)
self.initialized = True
except Exception as e:
raise RuntimeError(f"Failed to initialize DakkaBot: {str(e)}")
The class listing shows the split between constructing the service object and initializing its RAG resources. section 12.3


