# How i-RCFA Works This document explains how the memory-enabled i-RCFA application connects the chat screen, backend, databases, technical tools, and remote AI model. ## The big picture The AI is one worker inside the application, not the entire application. ```text User | v React chat screen | v Frontend nginx container | /ircfa is removed here v i-RCFA FastAPI backend :8005 | +--> PostgreSQL: chat history, RCFA state, model configuration, memories | +--> Technical tools: sensor, reliability, PFI, RCFA and plant-status APIs | +--> Remote Gemma service | v Streaming answer back to the browser ``` The current i-RCFA setup uses the established remote Gemma service. It does not use local Ollama, llama.cpp, or vLLM for the normal i-RCFA chat flow. ## 1. The browser The React frontend is responsible for: - displaying messages; - sending the user's question; - sending the login token; - displaying streamed answer text; - displaying tool/status events and suggested questions. The main chat request is in [`newChat.tsx`](fe-digitaltwin-v2/src/shared/components/rcfa-app/newChat.tsx). It sends a request to: ```text POST /ircfa/chat/stream ``` The request contains information such as: ```json { "messages": [ { "role": "user", "content": "What is the condition of 3DP-FDR711F?" } ], "conversation_id": "...", "location_tag": "3DP-FDR711F" } ``` The browser does not call Gemma directly. ## 2. Frontend nginx The frontend container uses nginx as a proxy. The nginx configuration is in [`nginx.conf`](fe-digitaltwin-v2/nginx.conf). When nginx receives: ```text /ircfa/chat/stream ``` it removes the `/ircfa` prefix and forwards the request to the backend: ```text http://host.docker.internal:8005/chat/stream ``` Therefore the first part of the real request path is: ```text Browser -> nginx -> backend port 8005 ``` Nginx also keeps the streaming connection open long enough for a remote model response. ## 3. FastAPI backend The backend route is in [`router.py`](be-ircfa/src/ircfa_interaction/router.py). The `POST /chat/stream` route: 1. reads the incoming JSON; 2. extracts the latest user message; 3. reads the conversation and equipment information; 4. reads uploaded files, if present; 5. identifies the authenticated user; 6. creates a structured `ChatRequest`; 7. starts the main orchestration function in [`stream2.py`](be-ircfa/src/ircfa_interaction/stream2.py). The backend is the control center. It decides what context and tools are available to the AI. ## 4. The orchestration layer The main function in `stream2.py` is the director of one chat turn. Before calling the model, it gathers: - recent conversation history; - the current RCFA state; - relevant private memories; - uploaded document content; - equipment and location information; - system instructions; - available technical tools. It then builds the complete model input. Conceptually, the model receives: ```text System instructions: You are an RCFA assistant. Follow memory privacy rules. Use technical tools when necessary. Conversation history: Previous questions and answers. Relevant memory: Active private memories that match the current question. Evidence: Sensor, reliability, PFI or document data. Current question: The user's latest message. ``` The model does not receive the entire database. The backend selects and prepares the information first. ## 5. The remote Gemma service The model adapter is [`gemma_llamacpp.py`](be-ircfa/src/ircfa_interaction/llm/gemma_llamacpp.py). It converts the backend request into an OpenAI-compatible request to: ```text https://gemma.digitaltwin.my.id/v1/chat/completions ``` The request can include: ```json { "model": "...", "messages": [], "tools": [], "tool_choice": "auto", "stream": true } ``` The active model information comes from the `rcfa_model_config` PostgreSQL table. This includes the model name, server URL, provider, streaming setting, and generation settings. The backend therefore communicates with Gemma like this: ```text i-RCFA backend -> remote Gemma API ``` It does not normally communicate with local Ollama. ## 6. How technical tools work Gemma cannot magically see the sensor or PFI database. The backend gives it a list of controlled tools. Examples include tools for: - current sensor data; - historical sensor data; - current reliability data; - PFI predictions; - failure modes; - root-cause information; - plant status. The tool loop looks like this: ```text User asks about sensor data | v Gemma decides it needs sensor information | v Gemma requests a technical tool | v i-RCFA backend executes that tool | v Tool calls the appropriate PFI/reliability API | v Tool result returns to the backend | v Backend gives the result back to Gemma | v Gemma explains the result to the user ``` For PFI sensor information, the usual relationship is: ```text Gemma -> i-RCFA tool -> PFI API -> PFI database or system ``` The AI normally does not directly query the PFI database. ## 7. Where memory fits Memory is loaded before the model is called. The backend: 1. searches memories belonging to the signed-in user; 2. ignores archived memories; 3. ignores expired memories; 4. scores memories for relevance; 5. gives pinned memories a small priority boost; 6. places relevant memories into the model context. Memory retrieval is implemented in [`stream2.py`](be-ircfa/src/ircfa_interaction/stream2.py). Memory saving happens after the response is completed. The backend only saves when the user explicitly asks it to remember something. The save path: ```text User explicitly asks to remember something | v Backend checks the request | +--> blocks obvious passwords, tokens and credentials | +--> checks for a duplicate | +--> checks the active-memory limit | v Memory is saved to PostgreSQL ``` The assistant's answer is not automatically turned into a memory. An explicit user request is required. ## 8. Streaming the answer The backend returns a streaming response instead of waiting for the complete answer. During one response it can send: - answer text; - tool progress; - usage information; - RCFA state; - suggested questions; - error events. The frontend reads these pieces from the response body and updates the chat screen while the answer is being generated. ```text Gemma produces a piece -> backend receives it -> backend sends it through the stream -> frontend reads it -> chat screen displays it ``` After the response is complete, the backend saves the conversation and any approved memory in the database. ## 9. What a 503 means A 503 means that a service was temporarily unavailable. In the common i-RCFA case, the failing link is near the remote Gemma service: ```text Browser -> nginx -> i-RCFA backend -> remote Gemma -> 503 ``` Possible causes include: - the remote model is overloaded; - the remote model is restarting; - too many requests arrived at once; - the remote proxy timed out; - the remote service temporarily rejected the request. A Gemma 503 does not automatically mean that the PFI database, sensor timestamp, memory, or frontend is broken. The useful debugging question is: which room failed? ```text Browser room Did the request leave the browser? Nginx room Did the proxy forward it? Backend room Did FastAPI start orchestration? Tool room Did the PFI/reliability API respond? Gemma room Did the remote AI answer? Database room Did chat/memory saving succeed? ``` ## The complete request loop ```text 1. Prepare context 2. Ask Gemma 3. Gemma may request a tool 4. Backend executes the tool 5. Backend returns the tool result to Gemma 6. Gemma writes the explanation 7. Backend streams the explanation to the browser 8. Backend saves the conversation ``` The most important architectural idea is that Gemma does not own the application. The backend controls what Gemma can see, which tools it can use, which user's memory it can receive, and how the final answer reaches the browser. ## Main files | Responsibility | File | |---|---| | Chat UI and streaming reader | [`newChat.tsx`](fe-digitaltwin-v2/src/shared/components/rcfa-app/newChat.tsx) | | Frontend-to-backend proxy | [`nginx.conf`](fe-digitaltwin-v2/nginx.conf) | | FastAPI chat routes | [`router.py`](be-ircfa/src/ircfa_interaction/router.py) | | Main AI orchestration | [`stream2.py`](be-ircfa/src/ircfa_interaction/stream2.py) | | Remote Gemma adapter | [`gemma_llamacpp.py`](be-ircfa/src/ircfa_interaction/llm/gemma_llamacpp.py) | | Model configuration | [`config.py`](be-ircfa/src/ircfa_interaction/config.py) and `rcfa_model_config` | | Memory privacy rules | [`memory_policy.py`](be-ircfa/src/ircfa_interaction/memory_policy.py) | | Memory lifecycle rules | [`memory_lifecycle.py`](be-ircfa/src/ircfa_interaction/memory_lifecycle.py) | | Memory Lab UI | [`MemoryLabModal.tsx`](fe-digitaltwin-v2/src/shared/components/rcfa-app/MemoryLabModal.tsx) |