Moufida is a local-first multimodal knowledge platform built around a transparent desktop overlay (Tauri + Next.js) and Python microservices for ingestion, search, organization, voice copilot, and knowledge-gap detection.
In Tunisian Arabic, “Moufida” conveys usefulness/helpfulness, which matches the product’s goal.
This stack is designed so your data pipeline stays local by default:
- Documents and media stay on your machine/network: files are ingested from local directories and local/controlled URLs.
- Embeddings are generated locally in the retrieval service (CLIP/BLIP/Whisper/Summarizer).
- Core storage is self-hosted (MongoDB + Qdrant).
- Vector explainability is enabled via XQdrant (a modified Qdrant fork used by this project).
- LLM serving strategy:
qwen3:4b-thinking-2507-q4_K_Mis run on a local PC and exposed through an OpenAI-compatible endpoint using ngrok so other PCs can reuse one strong model host.
The project uses qwen3:4b-thinking-2507-q4_K_M because it is considered a strong “performance-per-size” model in benchmark discussions and practical use. In this setup, the model runs on local hardware, while ngrok is used as a transport layer to share that local model endpoint across machines without moving the full data platform to cloud SaaS.
Desktop UI (Tauri + Next.js)
│
├── Retrieval Service (8100)
│ ├── local embeddings + ingest + graph
│ ├── MongoDB metadata
│ └── Qdrant vectors
│
├── Search Service (8400)
│ ├── semantic search over shared vectors
│ └── optional LLM reasoning/explanations
│
├── Organisation Service (8200)
│ ├── clustering and folder planning
│ └── applies file moves with DB updates
│
├── Copilot Voice Service (8300)
│ ├── chat
│ ├── speech-to-text
│ └── text-to-speech
│
└── Knowledge Gap Service (8000)
└── identifies unresolved/sparse knowledge areas
Shared dependencies:
- MongoDB (metadata + graph + timelines + chat)
- Qdrant / **XQdrant** (vector search + explainability)
- Local LLM host exposed via ngrok (OpenAI-compatible)
### XQdrant (modified Qdrant fork)
This project uses a modified Qdrant fork (XQdrant) to support similarity-score explainability in addition to standard vector search.
- Regular search works as usual.
- Explainable search can return contribution metadata (`score_explanation`) used by graph/agent UX.
- Retrieval and search services expose this through `with_explanation` request flags on relevant endpoints.
| Service | Path | Default Port | Purpose |
|---|---|---|---|
| Retrieval | backend/retrieval_service |
8100 | Ingestion, embeddings, graph, metadata, chat persistence |
| Organisation | backend/organisation_service |
8200 | Natural-language file organisation and move plans |
| Copilot Voice | backend/copilot_service |
8300 | LLM chat + STT + TTS + voice pipeline |
| Search | backend/search_service |
8400 | Semantic + agent-powered explainable search |
| Knowledge Gap | backend/knowledge_gap |
8000 | Gap detection and resolution APIs |
| UI (Next.js + Tauri) | ui |
3000 (web dev) | Overlay interface and install/deploy UI |
./scripts/setup.sh --uiFor full desktop prerequisites (Rust + Tauri system deps):
./scripts/setup.shcd backend/retrieval_service && python main.py
cd backend/organisation_service && python main.py
cd backend/copilot_service && python main.py
cd backend/search_service && python main.py
cd backend/knowledge_gap && uvicorn app:app --host 0.0.0.0 --port 8000 --reloadWeb mode:
cd ui
npm run devDesktop overlay:
cd ui
npm run tauri:devServices that call the LLM (search, organisation, copilot) use:
LLM_BASE_URLLLM_MODEL(defaultqwen3:4b-thinking-2507-q4_K_M)
Typical flow:
- Run your model server on a local machine.
- Expose it via ngrok (
https://...ngrok-free.app). - Point each service’s
LLM_BASE_URLto that ngrok URL.
This lets multiple workstations consume one local model host while preserving a local-first data architecture.
Moufida/
├── backend/
│ ├── retrieval_service/
│ ├── organisation_service/
│ ├── copilot_service/
│ ├── search_service/
│ └── knowledge_gap/
├── infrastructure/
│ └── observability/
├── ui/
├── scripts/
└── data/
Common checks:
# UI
cd ui && npm run build
cd ui && npm run lint
# Knowledge gap tests
cd backend/knowledge_gap && pytest tests -qService health examples:
curl http://127.0.0.1:8100/api/health
curl http://127.0.0.1:8200/api/status
curl http://127.0.0.1:8300/api/status
curl http://127.0.0.1:8400/api/status
curl http://127.0.0.1:8000/health