CVect 是一个面向招聘场景的简历处理与候选人管理系统,覆盖 JD 管理、简历上传解析、候选人列表、SSE 实时流 和 pgvector 语义检索。
项目当前默认形态已经收敛为:
- 三个编排入口:
docker-compose.yml、docker-compose.web.yml、docker-compose.embedding.yml - 三个配置文件:
.env、.env.web、.env.embedding - 一个可单独部署的模型服务:
Qwen - 三个运行脚本:
scripts/local-run.sh、scripts/server-run.sh、scripts/embedding-run.sh
| Item | Value |
|---|---|
| Public URL | http://111.228.5.197:8088/ |
| Username | demo |
| Password | demo123 |
| Access | Interviewer / demo access |
- JD create / update / delete
- Resume upload, ZIP upload, retry, dedupe
- Tika parsing and structured extraction
- Candidate list and recruitment status updates
- SSE batch and candidate streaming
- Vector search backed by
pgvector - Offline Hugging Face cache for
Qwen/Qwen3-Embedding-0.6B - Configurable file storage (
localand S3-compatible / MinIO)
Storage mode setup and validation are documented in docs/storage.md.
- Backend: Java 17, Spring Boot 3.5, Flyway, JPA
- Frontend: Vue 3, Vite 5
- Model service: FastAPI, Transformers, PyTorch CPU
- Database: PostgreSQL 17,
pgvector - Infra: Docker Compose
web host:
frontend -> nginx -> backend -> postgres
|
-> remote embedding service
embedding host:
qwen -> :8001
CVect/
├── backend/cvect/ # Spring Boot backend
├── frontend/ # Vue app
├── Qwen/ # FastAPI embedding service
├── scripts/ # run / deploy / cache scripts
├── docker-compose.yml # local all-in-one compose
├── docker-compose.web.yml
├── docker-compose.embedding.yml
├── .env # local development env
├── .env.web # web host env
└── .env.embedding # embedding host env
- Java 17
- Node.js 20+
- Python 3.10+
- Docker + Docker Compose
Edit .env first, then run:
If CVECT_BASIC_AUTH_ENABLED=true, set CVECT_BASIC_AUTH_USERNAME and CVECT_BASIC_AUTH_PASSWORD in .env before starting; the checked-in defaults intentionally leave those blank.
scripts/local-run.sh startUseful commands:
scripts/local-run.sh status
scripts/local-run.sh stop
scripts/local-run.sh restartLocal mode behavior:
postgresruns via Docker Composeqwenruns locally on:8001backendruns locally on:8080frontendruns locally on:5173- logs and pid files are written under
.run/
scripts/server-run.sh now manages only the web stack:
postgresbackendfrontend
Edit .env.web before starting the web host. It must point at the remote embedding service:
CVECT_EMBEDDING_SERVICE_URL=http://<embedding-host>:8001/embed
CVECT_EMBEDDING_HEALTH_URL=http://<embedding-host>:8001/readyThen start the web host:
scripts/server-run.sh upUseful commands:
scripts/server-run.sh status
scripts/server-run.sh logs
scripts/server-run.sh logs backend
scripts/server-run.sh down
scripts/server-run.sh restartscripts/server-run.sh up starts from existing images and will not build on the server. If you intentionally want to build the web images on the server, use scripts/server-run.sh up-build.
If .env.web still points to http://qwen:8001/..., scripts/server-run.sh fails fast instead of starting a local embedding container on the web host.
scripts/embedding-run.sh manages only the qwen service and is intended for the future GPU host.
Edit .env.embedding before starting the embedding host.
scripts/embedding-run.sh up-buildUseful commands:
scripts/embedding-run.sh status
scripts/embedding-run.sh logs
scripts/embedding-run.sh restart
scripts/embedding-run.sh downThe embedding host publishes qwen on CVECT_EMBEDDING_PUBLIC_PORT. Point the web host at that address through CVECT_EMBEDDING_SERVICE_URL and CVECT_EMBEDDING_HEALTH_URL.
The default model is Qwen/Qwen3-Embedding-0.6B.
The cache is prepared locally and mounted into the qwen container at /root/.cache/huggingface.
Prepare cache locally:
scripts/qwen-offline-cache.sh prefetch
scripts/qwen-offline-cache.sh verify
scripts/qwen-offline-cache.sh packAvailable cache commands:
scripts/qwen-offline-cache.sh info
scripts/qwen-offline-cache.sh prefetch
scripts/qwen-offline-cache.sh verify
scripts/qwen-offline-cache.sh pack
scripts/qwen-offline-cache.sh unpack /path/to/qwen-hf-cache.tgzIf you do not want remote machines to build images:
- Build locally
- Export the web images and embedding image separately
- Upload the matching image archive to each host
- Upload HF cache only to the embedding host
- Start each role with its dedicated script
Local:
docker compose --env-file .env -f docker-compose.yml build qwen backend frontend
docker pull m.daocloud.io/docker.io/pgvector/pgvector:pg17
docker save -o /tmp/cvect-web-images.tar \
cvect-backend:latest \
cvect-frontend:latest \
m.daocloud.io/docker.io/pgvector/pgvector:pg17
docker save -o /tmp/cvect-embedding-images.tar \
cvect-qwen:latest
gzip -c /tmp/cvect-web-images.tar > .artifacts/cvect-web-images.tgz
gzip -c /tmp/cvect-embedding-images.tar > .artifacts/cvect-embedding-images.tgz
scripts/qwen-offline-cache.sh packWeb host:
cp .env.web /opt/cvect/.env.web
gunzip -c cvect-web-images.tgz | docker load
scripts/server-run.sh up
scripts/server-run.sh statusEmbedding host:
cp .env.embedding /opt/cvect/.env.embedding
gunzip -c cvect-embedding-images.tgz | docker load
scripts/qwen-offline-cache.sh unpack /path/to/qwen-hf-cache.tgz
scripts/qwen-offline-cache.sh verify
scripts/embedding-run.sh up
scripts/embedding-run.sh statusLocal mode:
curl -fsS http://127.0.0.1:8001/health
curl -fsS http://127.0.0.1:8080/api/resumes/healthWeb host:
curl -u '<user>:<pass>' -fsS http://127.0.0.1:8088/healthz
scripts/server-run.sh statusEmbedding host:
curl -fsS http://127.0.0.1:8001/ready
scripts/embedding-run.sh statusBackend:
cd backend/cvect
./mvnw -q testFrontend:
cd frontend
npm testPython syntax/import checks:
python3 -m py_compile Qwen/embedding_service.pyRuntime behavior is split across the role-specific env files:
- local development:
.env - web host:
.env.web - embedding host:
.env.embedding
Important keys:
CVECT_HTTP_PORTCVECT_DB_URLCVECT_DB_USERNAMECVECT_DB_PASSWORDCVECT_EMBEDDING_SERVICE_URLCVECT_EMBEDDING_API_FORMATCVECT_EMBEDDING_HEALTH_URLCVECT_EMBEDDING_PUBLIC_PORTCVECT_EMBEDDING_MODELCVECT_EMBEDDING_BATCH_SIZECVECT_EMBEDDING_MAX_INPUT_LENGTHCVECT_CHUNK_MAX_LENGTHCVECT_VECTOR_ENABLEDCVECT_VECTOR_INGEST_WORKER_ENABLEDCVECT_HF_CACHE_DIRCVECT_HF_HUB_OFFLINECVECT_HF_LOCAL_FILES_ONLYJAVA_OPTS
Small machine defaults are already tuned for 2C4G:
- CPU-only embedding
- batch size
1 - max input length
1024 - conservative JVM memory
- Live demo URL can be linked from the GitHub repository "About" section.
- Web and embedding are now separate deployment roles.
qwenshould live on the embedding host only.- Frontend auth is configured at the nginx layer and should be managed via
.env.web. scripts/local-run.shremains the all-in-one local development entrypoint.
