Content
# CompassFXPulse
> Multi-currency foreign exchange risk management platform — Function Calling Agent + RAG + MCP Server + LoRA fine-tuning + TimeXer time series forecasting, end-to-end LLM application engineering practice.





---
## What is this
Reconstruct and upgrade the 2025 Citibank Cup project (Vue + Flask + LoRA fine-tuning + multi-source crawler) from "separate modules, demo can't run" to a **production-level LLM application stack**:
- 🤖 **Function Calling Agent** (LangGraph state machine + Reflector error correction closed loop)
- 📚 **RAG retrieval stack** (bge-m3 embedding + bge-reranker-v2-m3 re-ranking + ChromaDB + 30 curated financial corpus)
- 🔌 **MCP Server** (FastMCP, 5 tools synchronized exposure to Cursor / Claude Desktop)
- 🎯 **LoRA SFT** (Qwen3-1.7B + self-synthesized 200 Chinese financial Q&A, eval loss 4.85→1.30)
- 📈 **TimeXer time series forecasting** (Transformer, 25-year ECB long data + 4 sets of exogenous feature experiments)
- 🔍 **Langfuse full-link trace** (plan / tool / latency / token, elegant degradation)
- 💬 **Heterogeneous LLM routing** (DeepSeek cloud processing Agent, local LoRA processing Hui Ju answer query, one-line `.env` switching)
---
## System Architecture
> **Architecture diagram (including Phase 4 reinforcement)**: See `docs/diagrams/architecture.png` (high-definition complete diagram), the following mermaid is a simplified version.
```mermaid
graph TB
subgraph "User Entrance"
Browser["Browser :8081<br/>(Vue 2 + ECharts)"]
IDE["Cursor / Claude Desktop"]
BenchClient["Bench client<br/>(httpx async)"]
end
subgraph "Edge Defense (Phase 4.1+4.3)"
RateLimit["rate_limit.py<br/>token bucket per-IP<br/>10 rps + 20 burst"]
Guard["security/injection_guard.py<br/>5 layers defense<br/>96.8% interception rate"]
end
subgraph "Backend Flask :8080 (sync, WSGI)"
Routes["routes_chat / routes_agent / routes_rates / routes_health<br/>+ /api/cache/stats"]
Agent["agent/core.py<br/>Plan→Execute→Synth→Reflect<br/>MAX_TOOL_ROUNDS=2"]
Tools["agent/tools.py<br/>5 tools + validate_tool_args"]
Cache["cache.py (Phase 4.1)<br/>TTLCache / Redis<br/>~6500× acceleration"]
RAG["rag/pipeline.py<br/>bge-m3 + reranker"]
Obs["observability.py<br/>Langfuse"]
end
subgraph "Backend FastAPI :8082 (async, ASGI, Phase 4.4)"
FA["main_fastapi.py + routes_async.py<br/>200 concurrency 2.81× QPS"]
end
subgraph "Evaluation Framework (Phase 4.2)"
Eval["eval/run_eval.py<br/>30 gold set + 31 adversarial set<br/>pass 93.5% / judge 9.7"]
end
subgraph "MCP Server (stdio)"
MCP["mcp_server/server.py<br/>FastMCP"]
end
subgraph "LLM Routing"
DeepSeek["DeepSeek cloud<br/>(Agent tool decision + Judge)"]
LocalLoRA["Local Qwen3-1.7B-Finance :8001<br/>(Hui Ju answer query)"]
end
subgraph "Data Layer"
MySQL[("MySQL pool=20<br/>17K rows exchange rate<br/>900 rows prediction")]
Chroma[("ChromaDB<br/>251 chunks")]
Corpus["30 curated<br/>markdown corpus"]
end
Browser -->|HTTP/SSE| RateLimit
BenchClient --> FA
RateLimit --> Guard
Guard --> Routes
IDE -->|MCP/JSON-RPC| MCP
Routes --> Agent
FA -.async wrap.-> Agent
Agent --> Tools
Agent --> Obs
Tools --> Cache
Cache -.miss.-> RAG
Cache -.miss.-> MySQL
Tools --> RAG
Tools --> MySQL
RAG --> Chroma
RAG -.offline ingest.-> Corpus
Agent -.tools API.-> DeepSeek
Routes -.chat path.-> LocalLoRA
MCP -.reuse same tool set.-> Tools
Eval -.continuous verification.-> Agent
style Cache fill:#fff8e1
style Guard fill:#ffebee
style RateLimit fill:#ffebee
style FA fill:#e8f5e9
style Eval fill:#f3e5f5
```
## Agent State Machine (LangGraph)
```mermaid
graph LR
START([START]) --> Planner
Planner -->|tool_calls| Executor
Planner -->|no tools| Synthesizer
Executor -->|< 2 rounds| Planner
Executor -->|≥ 2 rounds| Synthesizer
Synthesizer --> Reflector
Reflector -->|score ≥ 7| Finalize
Reflector -->|score < 7, retry < 1| Synthesizer
Reflector -->|retry exhausted| Finalize
Finalize --> END([END])
style Planner fill:#fff8e1
style Executor fill:#e8f4fd
style Synthesizer fill:#f5f5f5
style Reflector fill:#f3e5f5
style Finalize fill:#c8e6c9
```
---
## Key Delivery Indicators
| Dimension | Number |
|---|---|
| **LoRA fine-tuning** | Qwen3-1.7B QLoRA r=16, eval loss **4.85 → 1.30** (−73%), token accuracy 0.43→0.70 |
| **TimeXer backtest** | USD/GBP **MAE −10.23%** vs ARIMA (25-year ECB + vol+mom+VIX+DXY) |
| **Agent evaluation** | **30 gold set pass 29/31=93.5%, LLM-as-Judge average 9.7/9.7/9.8 (accuracy/faithfulness/helpfulness)** |
| **MCP Server** | 5 tools + 1 resource, stdio + HTTP dual protocol, 3 PASS smoke test |
| **RAG retrieval** | 30 curated corpus → 251 chunks, end-to-end retrieval < 2s (including reranker) |
| **Data scale** | 6 currencies × 25 years = 7126 working days, 17,760 rows exchange rate, 900 rows SARIMAX prediction |
| **Code scale** | ~189 files / 16 MB, covering 4 engineering directions (Web / Agent / fine-tuning / time series) |
---
## Quick Start
> Assuming Python 3.12 + Node 16 + MySQL 8.x + 4 GB video memory GPU (CPU can also run, but slower)
### 1. Install Environment
```bash
conda create -n compass-fx python=3.12 -y
conda activate compass-fx
cd backend && pip install -r requirements.txt
```
### 2. Configure `.env`
```bash
cd backend && cp .env.example .env
# Edit .env, fill in at least:
# MYSQL_PASSWORD = your MySQL root password
# LLM_API_KEY = apply at https://platform.deepseek.com/ (recharge ¥10 is enough for a month)
```
### 3. Initialize Data + Index
```bash
cd backend
mysql -u root -p < scripts/init_db.sql # Create database + table
python scripts/refresh.py # Pull real exchange rate + generate SARIMAX prediction
python scripts/synthesize_corpus.py # (Optional) Synthesize 30 RAG corpus
python scripts/rebuild_rag.py --rebuild # (Optional) Build vector database (need to download bge-m3)
```
### 4. Start Backend + Frontend
```bash
# Terminal 1: Backend
python main.py
# Terminal 2: Frontend
cd frontend && npm install && npm run dev
# Browser http://localhost:8081
```
### 5. (Optional) Connect to Claude Desktop / Cursor's MCP
Refer to [`backend/mcp_server/README.md`](backend/mcp_server/README.md), copy [`claude_desktop_config.example.json`](backend/mcp_server/claude_desktop_config.example.json) to `%APPDATA%\Claude\claude_desktop_config.json`.
---
## Document Map
Each phase has independent engineering notes + interview Q&A:
| Phase | Document | One-sentence summary |
|---|---|---|
| Overview | [docs/Phase3_Overview.md](docs/Phase3_Overview.md) | 5 sub-stages + JD coverage matrix + 10-minute demo path |
| Maintenance and upgrade plan | [docs/Maintenance_and_Upgrade_Plan.md](docs/Maintenance_and_Upgrade_Plan.md) | Phase 0-5 overall plan (restart project overall plan) |
| Phase 2 LoRA | [docs/Phase2_Engineering_Notes.md](docs/Phase2_Engineering_Notes.md) / [Phase2_Completion_Report.md](docs/Phase2_Completion_Report.md) | QLoRA training + self-synthesized data + vLLM-style deployment |
| Phase 2 third-party comparison | [docs/LoRA_3way_comparison.md](docs/LoRA_3way_comparison.md) | DeepSeek vs Base Qwen3 vs LoRA fine-tuning, 8 questions comparison |
| Phase 3.1+3.2 RAG | [docs/Phase3_RAG.md](docs/Phase3_RAG.md) | bge-m3 + reranker + ChromaDB + Agent integration |
| Phase 3.3 MCP | [docs/Phase3_3_MCP.md](docs/Phase3_3_MCP.md) | FastMCP + Cursor / Claude Desktop access |
| Phase 3.4 Langfuse | [docs/Phase3_4_Langfuse.md](docs/Phase3_4_Langfuse.md) | Full-link trace + elegant degradation |
| Phase 3.5 LangGraph | [docs/Phase3_5_LangGraph.md](docs/Phase3_5_LangGraph.md) | Multi-Agent state machine + Reflector error correction |
| **TimeXer backtest** | [docs/TimeXer_Backtest_Actuals.md](docs/TimeXer_Backtest_Actuals.md) | **8 experiments + scaling experiment + 5 layers interview Q&A** |
| **Phase 4.1 cache and concurrency** | [docs/Phase4_1_Cache_and_Concurrency.md](docs/Phase4_1_Cache_and_Concurrency.md) | **Cache layer + connection pool + current limiting, measured ~6500× acceleration** |
| **Phase 4.2 evaluation set** | [docs/Phase4_2_Evaluation_Set.md](docs/Phase4_2_Evaluation_Set.md) | **30 questions + LLM-as-Judge + ablation control, pass 93.5% / judge 9.7** |
| **Phase 4.3 injection defense** | [docs/Phase4_3_Injection_Defense.md](docs/Phase4_3_Injection_Defense.md) | **5 layers depth defense + 31 adversarial samples, interception rate 96.8%** |
| **Phase 4.4 FastAPI asynchronous** | [docs/Phase4_4_FastAPI_Asynchronous.md](docs/Phase4_4_FastAPI_Asynchronous.md) | **ASGI parallel deployment + measured 200 concurrency QPS improvement 2.24×/2.61×/2.81×** |
---
## Switch LLM Provider
Just modify `.env` 4 lines, no need to change code:
| Provider | LLM_BASE_URL | LLM_MODEL |
|---|---|---|
| **DeepSeek** (default) | `https://api.deepseek.com/v1` | `deepseek-chat` |
| Alibaba Cloud Qwen | `https://dashscope.aliyuncs.com/compatible-mode/v1` | `qwen-plus` |
| Local Ollama | `http://127.0.0.1:11434/v1` | `qwen3:8b` |
| OpenAI | `https://api.openai.com/v1` | `gpt-4o-mini` |
| **Local LoRA** (self-trained) | `http://127.0.0.1:8001/v1` | `qwen3-1.7b-finance` |
Heterogeneous routing (Agent goes to DeepSeek, Hui Ju answer query goes to local LoRA): fill in `LLM_AGENT_*` and `LLM_CHAT_*` respectively.
---
## Tech Stack
```
Backend Flask 3.0 · MySQL 8 · OpenAI Python SDK · Langfuse 4.5
RAG ChromaDB · bge-m3 · bge-reranker-v2-m3 · transformers 5.6
Agent LangGraph 1.1 · LangChain Core 1.3 · DeepSeek tools API
MCP mcp 1.27 (FastMCP)
Fine-tuning PyTorch 2.6 + cu124 · peft 0.19 · trl 1.3 · bitsandbytes 0.49
Time series statsmodels 0.14 (SARIMAX) · TimeXer (Tsinghua original)
Frontend Vue 2.5 · ElementUI 2.15 · ECharts 5 · Webpack 3 · Marked + DOMPurify
Observation Langfuse cloud / self-hosted
```
## Roadmap
```
Phase 0 ✅ Web application rescue + DeepSeek connection + real data refill
Phase 2 ✅ LoRA Qwen3-1.7B financial domain SFT + FastAPI inference service
Phase 3.1 ✅ RAG retrieval stack (bge-m3 + reranker + ChromaDB + 30 curated corpus)
Phase 3.2 ✅ Function Calling Agent (5 tools + three-layer defense + trace visualization)
Phase 3.3 ✅ MCP Server (exposed to Cursor / Claude Desktop)
Phase 3.4 ✅ Langfuse full-link trace
Phase 3.5 ✅ LangGraph multi-Agent + Reflector error correction
Phase 4.1 ✅ Cache layer (TTL/Redis can be switched) + connection pool + current limiting (QPS 5→50-100, cache hit ~6500× acceleration)
Phase 4.2 ✅ 30 gold set + LLM-as-Judge + ablation control (pass 29/31=93.5%, judge average 9.7/10)
Phase 4.3 ✅ Prompt injection 5 layers depth defense + 31 adversarial samples (interception rate 30/31=96.8%)
Phase 4.4 ✅ FastAPI ASGI parallel deployment (measured 50/100/200 concurrency QPS improvement 2.24×/2.61×/2.81×)
Phase 4.5 📅 vLLM deployment local LoRA
Phase 4.6 📅 Skill package (forex-pulse.skill)
```
---
## Acknowledgements
- Phase 0 reconstruction based on 2025 Citibank Cup (CompassFXPulse) project source code
- Original project design: Citibank Cup participating team
- Reconstruction, Agent / RAG / MCP / LoRA transformation, TimeXer experiment: [xzzzzc217](https://github.com/xzzzzc217) (Southeast University network space security / 2027)
## License
MIT — see [LICENSE](LICENSE).
Connection Info
You Might Also Like
Vibe-Trading
Vibe-Trading: Your Personal Trading Agent
ai-berkshire
Berkshire in the AI Era: A Value Investment Research Framework Based on...
hexstrike-ai
HexStrike AI is an AI-powered MCP cybersecurity automation platform with 150+ tools.
valuecell
Valuecell is a Python project for efficient data management.
tradingview-mcp
AI-assisted TradingView chart analysis — connect Claude Code to your...
tradingview-mcp
TradingView MCP Server offers real-time market analysis for crypto and stocks.