Private
Public Access
chore(docs): organize reports into week folders (113 files, 6 weeks)
Moves 113 loose files in docs/reports/ into week folders named <YYYY>-<MM>-<DD> (Monday of the file's week). Weeks created: 2026-03-02, 2026-05-04, 2026-05-11, 2026-06-01, 2026-06-08, 2026-06-15. Current week's files (June 22+) stay in place; 23 in-flight reports remain in docs/reports/ root. Subdirectories code_path_audit/ and license_cve_audit/ untouched.
This commit is contained in:
@@ -1,121 +0,0 @@
|
||||
# AI Client Decoupling - Attempted and Reverted
|
||||
|
||||
**Date:** 2026-05-13
|
||||
**Status:** REVERTED
|
||||
|
||||
## Summary
|
||||
|
||||
An attempt was made to decouple the AI client library imports from the main GUI application to reduce startup time. The core issue was slow startup due to heavy SDK imports (`google.genai`, `anthropic`, `chromadb`). The decoupling was only partially implemented and ultimately determined to be unnecessary since the actual bottleneck was RAG initialization, not AI SDK imports.
|
||||
|
||||
## What Was Attempted
|
||||
|
||||
### 1. Created `ai_client_stub.py`
|
||||
A lightweight stub module that provides a minimal interface to AI client functionality without importing heavy SDKs. The stub was intended to route all AI calls to a separate AI server process.
|
||||
|
||||
### 2. Module Replacement Pattern in `sloppy.py`
|
||||
```python
|
||||
# Route all ai_client imports to ai_client_stub to avoid loading heavy SDKs
|
||||
if os.environ.get("AI_SERVER_ENABLED"):
|
||||
import sys
|
||||
from src import ai_client_stub
|
||||
sys.modules["src.ai_client"] = ai_client_stub
|
||||
```
|
||||
|
||||
### 3. Lazy Loading of RAG
|
||||
Moved `rag_engine` import from module-level to lazy imports inside functions/setters.
|
||||
|
||||
### 4. Async RAG Initialization
|
||||
Moved RAG engine initialization to a background thread to prevent blocking the UI during startup.
|
||||
|
||||
## What Actually Fixed the Startup Issue
|
||||
|
||||
**The primary startup bottleneck was RAG initialization (5+ seconds), not AI SDK imports.**
|
||||
|
||||
Timeline of discovery:
|
||||
1. Initial timing showed ~1.4s for `app_controller` import
|
||||
2. Further profiling revealed `rag_engine` → `chromadb` import chain at module level
|
||||
3. Lazy loading of `rag_engine` reduced startup to ~0.4s
|
||||
4. Further profiling showed `init_state()` taking 5+ seconds
|
||||
5. Discovered `models.RAGConfig.from_dict()` was parsing with RAG enabled in config
|
||||
6. Making RAG initialization async reduced App() construction from 5.2s to 0.027s
|
||||
|
||||
## Why Decoupling Was Not Fully Implemented
|
||||
|
||||
1. **Incomplete module replacement:** The `sys.modules["src.ai_client"] = ai_client_stub` approach was fragile and not consistently applied. Multiple modules still imported `ai_client` directly.
|
||||
|
||||
2. **AI Server never properly utilized:** The `ai_client_proxy` and server infrastructure existed but was never properly integrated. The proxy client was designed to spawn a subprocess and communicate via JSON-RPC, but this was never connected to actual AI calls.
|
||||
|
||||
3. **Wrong diagnosis:** The real issue was RAG blocking the event loop, not AI SDK imports. Even if decoupling worked fully, it wouldn't have addressed the primary bottleneck.
|
||||
|
||||
4. **Architectural complexity:** The decoupling added significant complexity (stub modules, proxy client, server process, IPC mechanism) without proportional benefit.
|
||||
|
||||
## Files Modified During Attempt
|
||||
|
||||
### Created
|
||||
- `src/ai_client_stub.py` - Lightweight stub module
|
||||
|
||||
### Modified
|
||||
- `sloppy.py` - Added AI_SERVER_ENABLED routing
|
||||
- `src/app_controller.py` - Lazy rag_engine import, async RAG init
|
||||
|
||||
## Files That Were Deleted
|
||||
|
||||
The following files were created during the attempt and subsequently deleted:
|
||||
|
||||
| File | Size | Purpose | Deleted |
|
||||
|------|------|---------|---------|
|
||||
| `src/ai_client_stub.py` | 14KB | Lightweight stub module for routing AI calls | ✅ (commit b2fdca0c) |
|
||||
| `src/ai_client_proxy.py` | 3.6KB | Proxy client for spawning AI server subprocess | ✅ (commit b2fdca0c) |
|
||||
|
||||
## Cleanup Commits
|
||||
|
||||
### Commit b2fdca0c (2026-05-13)
|
||||
```
|
||||
remove(ai_client): delete unused stub and proxy files
|
||||
|
||||
Deleted:
|
||||
- src/ai_client_stub.py
|
||||
- src/ai_client_proxy.py
|
||||
|
||||
Fixed test imports to use ai_client instead of ai_client_stub.
|
||||
```
|
||||
|
||||
### Commit 4025a713 (2026-05-13)
|
||||
```
|
||||
revert(ai_client): remove incomplete decoupling, restore clean startup
|
||||
|
||||
The AI client decoupling was never properly implemented and added
|
||||
unnecessary complexity. The actual startup bottleneck was RAG initialization
|
||||
which is now handled via async initialization.
|
||||
|
||||
Report written to docs/reports/ai_decoupling_revert_report.md
|
||||
```
|
||||
|
||||
## Current State
|
||||
|
||||
After reverting the decoupling attempt:
|
||||
|
||||
| Metric | Time |
|
||||
|--------|------|
|
||||
| App class load | 0.4s |
|
||||
| App() construction | 0.027s |
|
||||
| RAG initialization | Async (background thread) |
|
||||
|
||||
The application now starts quickly with RAG loading in the background.
|
||||
|
||||
## Recommendations (Completed)
|
||||
|
||||
1. ✅ **Cleanup done:** `ai_client_stub.py`, `ai_client_proxy.py` deleted, `sloppy.py` restored
|
||||
|
||||
2. **If AI server is needed in future:** Implement properly as a separate concern, not as a module replacement hack
|
||||
|
||||
3. **Keep async RAG init:** The background thread for RAG is a good pattern and should remain
|
||||
|
||||
4. **Profile before optimizing:** The lesson learned is to profile before attempting architectural changes
|
||||
|
||||
## Lessons Learned
|
||||
|
||||
1. Measure first, optimize second - the actual bottleneck was discovered through profiling, not assumption
|
||||
2. Architectural changes should solve actual problems, not anticipated ones
|
||||
3. Partial decoupling is worse than no decoupling - it adds complexity without benefits
|
||||
4. The simplest fix is often correct - lazy imports and async initialization solved the problem without architectural overhaul
|
||||
Reference in New Issue
Block a user