Pisces is the first practical cryptography-based RAG framework that supports dual-path retrieval (BM25 and embedding similarity), while simultaneously protecting both the user query and the document corpus under a semi-honest two-party model.
For full technical details, please refer to our paper.
- Background
- Key Features
- Architecture Overview
- Project Structure
- Requirements
- Getting Started
- Running Examples
- Contributing
- Citation
- Acknowledgments
- License
Retrieval-Augmented Generation (RAG) pipelines typically send raw user queries to a server holding plaintext documents—exposing sensitive information on both sides. Pisces addresses this by replacing every retrieval step with cryptographic protocols (Label PSI, Fuzzy PSI, Garbled Circuits, PIR-to-Share, HE) so that neither party learns anything beyond what is strictly necessary.
- Dual-path secure retrieval — supports both BM25 (keyword) and cosine-similarity (embedding) ranking in a single unified framework.
- End-to-end privacy — the server never sees the query; the client never sees the raw documents.
- Practical performance — sub-second single-query latency on standard hardware; see the paper for full benchmark results.
- Modular cryptographic building blocks — Label PSI, Fuzzy PSI (32/64-bit), Garbled-Circuit Top-K, PIR-to-Share, and lightweight HE, each independently usable and benchmarkable.
- Bazel-based reproducible build — all dependencies are pinned and fetched automatically.
User (Client) Server
──────────────────────────────────────────────────────────────
Query tokens / embedding Document corpus
│ │
Label PSI / FuzzyPSI ◄────────────► Label PSI / FuzzyPSI
│ │
Secure BM25 / Similarity score share │
│ │
GC-based Top-K ◄────────────────── GC-based Top-K
│ │
PIR-to-Share ◄─────────────────── PIR-to-Share
│
Retrieved document features (secret share)
.
├── baseline/ # DP-based and remote-RAG baselines
├── bazel/ # Bazel build configuration and patches
├── pisces/ # Core library and applications
│ ├── example/ # End-to-end RAG example programs
│ │ ├── bm25/ # Secure BM25 RAG benchmark
│ │ └── similarity/ # Secure similarity RAG benchmark
│ ├── bench/ # Micro-benchmarks for each crypto module
│ ├── bm25/ # Secure BM25 scoring protocol
│ ├── gc/ # Garbled-circuit Top-K module
│ ├── suda/ # PIR and PIR-to-share module
│ ├── lpsi/ # Label PSI module
│ ├── fpsi/ # Fuzzy PSI module (32-bit & 64-bit)
│ ├── he/ # Lightweight homomorphic encryption primitives
│ ├── field/ # Finite field ops & threshold secret sharing
│ ├── okvs/ # OKVS implementation
│ ├── simhash/ # Locality-sensitive hash primitives
│ ├── similarity/ # Secure similarity scoring protocol
│ ├── cuckoo/ # Cuckoo hashing
│ └── x25519/ # X25519 / Monocypher primitives
├── preprocess/ # Data preprocessing scripts for RAG datasets
├── script/ # Plotting and analysis helper scripts
└── MODULE.bazel # Bazel module configuration
| Requirement | Version |
|---|---|
| Operating System | Linux, macOS |
| Build Tool | Bazel 6.0+ |
| C++ Compiler | C++17 — GCC 8+ or Clang 10+ |
| Other Dependencies | Managed automatically by Bazel |
# macOS (Homebrew)
brew install bazelisk cmake ninja nasm automake libtool libomp
# Linux — see https://bazel.build/install for distribution-specific instructionsgit clone https://github.com/ant-intl/Pisces.git
cd Piscesmake fetchThis downloads and caches the Bazel dependencies in distdir before building or testing.
make unittest
# equivalent to: bazel test -c opt --distdir=distdir //...The full integration test builds the protocol examples, generates preprocessed data, then runs the BM25 and similarity end-to-end tests:
make test
# generates data, then builds and runs the BM25 and similarity protocol testsOn success, the tests write the following files in the repository root:
| Test | Output |
|---|---|
| BM25 | bm25_result.jsonl |
| Similarity | sim_result.jsonl |
Each JSONL line contains one query result. results and scores are aligned arrays; upload and download are measured in MiB, and query_time is measured in seconds. The BM25 output also reports per-stage lpsi, bm25, topk, and suda metrics; the similarity output reports fpsi, sim, topk, and suda metrics. These files are overwritten on each run and ignored by Git through the *.jsonl rule.
make test internally calls make data, which runs preprocess/beir_process.py to tokenize and embed the dataset. This step requires Python with the following packages:
pip install pandas numpy tqdm transformers sentence-transformers langchain-coreIt will also automatically download two models from Hugging Face on first run:
| Model | Purpose |
|---|---|
bert-base-uncased |
BERT tokenizer for BM25 token extraction |
ibm-granite/granite-embedding-small-english-r2 |
Sentence embedding for similarity retrieval |
Note (China mainland): The script automatically sets
HF_ENDPOINT=https://hf-mirror.comto use the Hugging Face mirror. No manual configuration is needed.
bazel build -c opt --distdir=distdir //...To build individual modules:
bazel build -c opt --distdir=distdir //pisces/suda:...
bazel build -c opt --distdir=distdir //pisces/gc:...
bazel build -c opt --distdir=distdir //pisces/lpsi:...End-to-end RAG examples are located under pisces/example/.
# Build
bazel build -c opt --distdir=distdir //pisces/example/bm25:bm25_rag_bench
# Run with default settings
bazel run -c opt --distdir=distdir //pisces/example/bm25:bm25_rag_bench
# Run with custom parameters
bazel run -c opt --distdir=distdir //pisces/example/bm25:bm25_rag_bench -- \
--database_path=preprocess/data/bm25_corpus.jsonl \
--query_path=preprocess/data/bm25_query.jsonl \
--query_index=0 \
--K=10 \
--truncate_bit=10 \
--sort_bit=12| Parameter | Description | Default |
|---|---|---|
--database_path |
Path to the document corpus (JSONL) | built-in clapnq data |
--query_path |
Path to the query file (JSONL) | built-in clapnq data |
--query_index |
Index of the query to process | 0 |
--K |
Number of top-K documents to retrieve | 10 |
--truncate_bit |
Score truncation bits for Top-K | 10 |
--sort_bit |
Comparison bits for Top-K sort | 12 |
# Build
bazel build -c opt --distdir=distdir //pisces/example/similarity:similarity_rag_bench
# Run with default settings
bazel run -c opt --distdir=distdir //pisces/example/similarity:similarity_rag_bench
# Run with custom parameters
bazel run -c opt --distdir=distdir //pisces/example/similarity:similarity_rag_bench -- \
--database_path=preprocess/data/sim_corpus.jsonl \
--query_path=preprocess/data/sim_query.jsonl \
--query_index=0 \
--K=10 \
--truncate_bit=18 \
--sort_bit=14 \
--projection_weight=16 \
--projection_num=160| Parameter | Description | Default |
|---|---|---|
--database_path |
Path to the document corpus (JSONL) | built-in clapnq data |
--query_path |
Path to the query file (JSONL) | built-in clapnq data |
--query_index |
Index of the query to process | 0 |
--K |
Number of top-K documents to retrieve | 10 |
--truncate_bit |
Score truncation bits for Top-K | 18 |
--sort_bit |
Comparison bits for Top-K sort | 14 |
--projection_weight |
Fuzzy PSI random-projection weight | 16 |
--projection_num |
Number of random projections | 160 |
We welcome contributions of all kinds — bug reports, feature requests, documentation improvements, and pull requests.
- Fork the repository and create a feature branch.
- Ensure all existing tests pass:
make unittest - Add tests for any new functionality.
- Format code with
.reformat.shbefore submitting. - Open a pull request describing your changes.
Please read our LEGAL.md before contributing.
If you use Pisces in your research, please cite our paper:
@inproceedings{pisces2026,
title = {Pisces: Cryptography-based Private Retrieval-Augmented Generation with Dual-Path Retrieval},
author = {Liang, Xiaojian and Song, Lushan and Du, Shishuai and Zhu, Weicheng and Faith, Tan and Sim, Jun Jie and Jin, Haibing and Wu, Zhenghao and Liu, Yingting and Zhang, Xin and Yang, Jiangming and Duan, Pu},
booktitle = {Proceedings of the International Conference on Learning Representations (ICLR)},
year = {2026},
url = {https://openreview.net/pdf?id=Re3A6vzCTC}
}Pisces builds on the following excellent open-source projects:
Library Dependencies
| Project | Description |
|---|---|
| yacl | Basic cryptographic library providing PRG, OT, and network interfaces |
| SPU | SecretFlow-SPU: privacy-preserving machine learning runtime |
| OpenPanther | Efficient secure sorting protocol for private approximate nearest-neighbor search |
| Suda | Secure PIR and PIR-to-share protocol for unbalanced data alignment |
| GMP | GNU Multiple Precision Arithmetic Library, used by NTL (LGPLv3) |
| NTL | A Library for doing Number Theory, used in polynomial operations (LGPLv2.1+) |
| emp-tool | EMP toolkit core: garbled circuits, OT primitives, and I/O (MIT) |
| emp-ot | EMP oblivious transfer library (IKNP, Ferret COT), used in gc/ (MIT) |
Embedded Third-Party Source Code
The following open-source code is directly embedded in this repository. See the NOTICE files in the respective directories for full attribution and license details.
| Project | Directory | License |
|---|---|---|
| Monocypher — Loup Vaillant | pisces/x25519/ |
BSD-2-Clause OR CC0-1.0 |
| private-membership — Google | pisces/okvs/ |
Apache 2.0 |
| shell-encryption — Google | pisces/field/ |
Apache 2.0 |
| static_reflection — BOT Man JL | pisces/ |
MIT |
Pisces is released under the Apache License 2.0.
Copyright 2026 Ant International, Ant Group. All rights reserved.