liveBook · Manning

Separation of concerns

As explained in Machine Learning Platform Engineering

Separation of concerns is a software design principle that isolates distinct responsibilities into separate components or layers.

A chat interface should not own the retrieval and generation logic it displays. Put that logic in a reusable core, then let each interface handle its own interaction with users. The same core can serve a web chat, an API, or batch processing without duplicating the RAG workflow. 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 core holds the retriever, vector store, and language model. Its separate async initialization step handles resources that take time to load; an initialized flag records whether queries can safely run. section 12.3

Keep interface-specific startup and message handling outside the core. A Chainlit handler can initialize the core, validate input, and display streaming results while the core performs query processing. This boundary supports testing, maintenance, and alternative deployments. section 12.3

How Machine Learning Platform Engineering covers it

How deep it goes
Works through core extraction, async initialization, query methods, and Chainlit integration.
Examples
Uses a reusable RAG class and Chainlit startup and message handlers.
What it assumes
Assumes a minimal RAG implementation exists and introduces Chainlit installation before building its UI.
What you can do after
Build it from scratch by extracting RAG logic into a reusable core and connecting it to a Chainlit interface.
How it connects
Connects separation of concerns to retrieval-augmented generation, lazy initialization, streaming responses, and input validation.

Also explained in

Compare how 22 books explain separation of concerns →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Machine Learning Platform Engineering. The section links point to the parts of the book it draws on.