# Conflicts: # .github/workflows/benchmarks.yaml # .github/workflows/cifar_benchmark.yaml # .github/workflows/continuous-integration.yaml # .github/workflows/llama_finetuning_benchmark.yaml # .github/workflows/publish_aws_ami.yaml # .github/workflows/release.yaml # .github/workflows/resnet_hybrid_model.yaml # .github/workflows/sync_on_push.yaml # .github/workflows/weekly_tests.yaml # LICENSE # Makefile # README.md # UPGRADING.md # benchmarks/common.py # ci/aws_ami_build_component.yaml # conftest.py # docs/README.md # docs/SUMMARY.md # docs/advanced_examples/ClassifierComparison.ipynb # docs/advanced_examples/FullyConnectedNeuralNetwork.ipynb # docs/advanced_examples/FullyConnectedNeuralNetworkOnMNIST.ipynb # docs/advanced_examples/GLMComparison.ipynb # docs/advanced_examples/QuantizationAwareTraining.ipynb # docs/advanced_examples/RegressorComparison.ipynb # docs/advanced_examples/SVMClassifier.ipynb # docs/advanced_examples/utils/classifier_comparison_utils.py # docs/conventions.md # docs/deep-learning/fhe_assistant.md # docs/deep-learning/fhe_friendly_models.md # docs/developer/contributing.md # docs/developer/debug_support_submit_issues.md # docs/developer/project_setup.md # docs/explanations/compilation.md # docs/explanations/pruning.md # docs/getting-started/README.md # docs/getting-started/concepts.md # docs/getting-started/pip_installing.md # docs/guides/client_server.md # docs/references/api/concrete.ml.search_parameters.p_error_search.md # docs/references/api/concrete.ml.sklearn.base.md # docs/references/api/concrete.ml.sklearn.glm.md # docs/references/api/concrete.ml.sklearn.linear_model.md # docs/references/api/concrete.ml.sklearn.neighbors.md # docs/references/api/concrete.ml.sklearn.rf.md # docs/references/api/concrete.ml.sklearn.svm.md # docs/references/api/concrete.ml.sklearn.tree.md # docs/references/api/concrete.ml.sklearn.tree_to_numpy.md # docs/references/api/concrete.ml.sklearn.xgb.md # docs/tutorials/showcase.md # pyproject.toml # script/actions_utils/monitor.py # script/doc_utils/check_forbidden_words.py # script/make_utils/check_installation_with_all_python.sh # script/make_utils/check_issues.py # script/make_utils/fix_omp_issues_for_intel_mac.sh # script/make_utils/jupyter.sh # script/make_utils/local_link_check.py # src/concrete/ml/common/serialization/__init__.py # src/concrete/ml/common/serialization/encoder.py # src/concrete/ml/common/utils.py # src/concrete/ml/deployment/fhe_client_server.py # src/concrete/ml/onnx/convert.py # src/concrete/ml/onnx/onnx_model_manipulations.py # src/concrete/ml/onnx/onnx_utils.py # src/concrete/ml/onnx/ops_impl.py # src/concrete/ml/pandas/_development.py # src/concrete/ml/pandas/_operators.py # src/concrete/ml/pandas/_processing.py # src/concrete/ml/pandas/client_engine.py # src/concrete/ml/pandas/dataframe.py # src/concrete/ml/pytest/utils.py # src/concrete/ml/quantization/base_quantized_op.py # src/concrete/ml/quantization/linear_op_glwe_backend.py # src/concrete/ml/quantization/post_training.py # src/concrete/ml/quantization/quantized_module.py # src/concrete/ml/quantization/quantized_ops.py # src/concrete/ml/quantization/quantizers.py # src/concrete/ml/search_parameters/p_error_search.py # src/concrete/ml/sklearn/_fhe_training_utils.py # src/concrete/ml/sklearn/base.py # src/concrete/ml/sklearn/glm.py # src/concrete/ml/sklearn/linear_model.py # src/concrete/ml/sklearn/neighbors.py # src/concrete/ml/sklearn/qnn.py # src/concrete/ml/sklearn/tree_to_numpy.py # src/concrete/ml/sklearn/xgb.py # src/concrete/ml/torch/compile.py # src/concrete/ml/torch/hybrid_model.py # src/concrete/ml/torch/lora.py # tests/common/test_pbs_error_probability_settings.py # tests/common/test_serialization.py # tests/deployment/test_client_server.py # tests/onnx/test_onnx_utils.py # tests/pandas/test_pandas.py # tests/parameter_search/test_p_error_binary_search.py # tests/quantization/test_compilation.py # tests/quantization/test_quantized_module.py # tests/quantization/test_quantized_ops.py # tests/sklearn/test_dump_onnx.py # tests/sklearn/test_sklearn_models.py # tests/torch/test_brevitas_qat.py # tests/torch/test_compile_keras.py # tests/torch/test_compile_torch.py # tests/torch/test_torch_to_numpy.py # tests/torch/test_training.py # use_case_examples/cifar/README.md # use_case_examples/cifar/cifar_brevitas_finetuning/PerrorImpactOnFMNIST.ipynb # use_case_examples/cifar/cifar_brevitas_finetuning/README.md # use_case_examples/cifar/cifar_brevitas_finetuning/cifar_utils.py # use_case_examples/cifar/cifar_brevitas_training/evaluate_one_example_fhe.py # use_case_examples/cifar/cifar_brevitas_training/evaluate_torch_cml.py # use_case_examples/cifar/cifar_brevitas_training/trainer.py # use_case_examples/credit_card_approval_prediction/README.md # use_case_examples/deployment/sentiment_analysis/train.py # use_case_examples/deployment/server/deploy_to_docker.py # use_case_examples/disease_prediction/HealthCarePrediction.ipynb # use_case_examples/image_filtering/README.md # use_case_examples/llm/README.md # use_case_examples/llm/quant_framework.py # use_case_examples/lora_finetuning/README.md # use_case_examples/lora_finetuning/data_finetune/what_is_fhe.txt # use_case_examples/sentiment_analysis_with_transformer/SentimentClassification.ipynb # use_case_examples/titanic/KaggleTitanic.ipynb # use_case_examples/titanic/README.md # use_case_examples/white_paper_experiment/WhitePaperExperiments.ipynb
Privacy Preserving Language Models LoRA Fine-tuning
This use case demonstrates how to fine-tune language models (GPT-2 and LLaMA) using Low-Rank Adaptation (LoRA) weights with Fully Homomorphic Encryption (FHE). The goal is to train specialized models in a privacy-preserving manner, with minimal memory requirements.
Overview
Fine-tuning large language models typically requires access to sensitive data, which can raise privacy concerns. By leveraging FHE, we can perform computations on encrypted foundation model weights, ensuring that the data remain private throughout the training process. The LoRA weights are kept in clear on the client side.
Key Features
- LoRA Fine-Tuning: Fine-tune language models by adapting low-rank weights
- Hybrid Model: Combine encrypted foundation model weights with clear LoRA weights for optimal performance
- Low Memory Requirements: Minimal client-side memory needed for LoRA weights
- Multiple Approaches:
- Custom training implementation for GPT-2
- Simplified API-based approach for LLaMA using the
LoraTrainer
Setup
Installation
Install the required packages:
pip install -r requirements.txt
Usage
Available Notebooks
The repository includes two example notebooks:
-
GPT2FineTuneHybrid.ipynb:
- Uses a custom training implementation
- Fine-tunes GPT-2 on a small Q&A data-set about FHE
- Shows low-level control over the training process
-
LLamaFineTuning.ipynb:
- Uses TorusML's
LoraTrainerAPI for simplified implementation - Fine-tunes LLaMA on TorusML code examples
- Shows how to use the high-level API for encrypted fine-tuning
- Uses TorusML's
Prepare the data-set
Each notebook includes its own data-set:
- GPT-2 uses a small Q&A data-set about FHE in
data_finetune/what_is_fhe.txt - LLaMA uses TorusML code examples in
data_finetune/data-set.jsonl
Run the Fine-Tuning Script
Execute the Jupyter notebook GPT2FineTuneHybrid.ipynb to start the fine-tuning process. The notebook is structured into several steps:
Evaluation Script
The repository includes an evaluation script (eval.py) that allows you to train, evaluate and compare the LLaMA model training with different modes:
python eval.py --mode [torch|8bit|16bit]
The script supports three modes:
torch: Regular PyTorch training without quantization8bit: Training with 8-bit quantization16bit: Training with 16-bit quantization
The script will:
- Train the model on a math word problems dataset
- Generate evaluation metrics and sample responses
- Save the results in mode-specific files:
- Training logs:
training_log_{mode}.txt - Generated responses:
eval_generated_responses_{mode}.txt - Model weights:
deployment/llama_lora_finetuned_{mode}/
- Training logs:
Deployment/Production Scenario
In a deployment or production scenario, the model can be fine-tuned as follows:
- Server Setup: The server hosts a foundation model with generic weights.
- Client Setup: The user (client) has a set of LoRA weights and the sensitive data required for fine-tuning.
- Fine-Tuning Process:
- The client requests inference and backward passes from the server, which uses the generic weights/parameters.
- Any computation that requires the LoRA weights is executed on the client's end.
- Storage: The LoRA weights are stored on the client's end for later inference, ensuring full privacy of both the specialized model and the sensitive data.
Results
GPT-2 Results
After fine-tuning, the model's weights are distributed between the client and server as follows:
- Total weights removed from the server: 68.24%
- LoRA weights kept on the client: 147,456 (approximately 0.12% of the original model's weights)
Note that the embeddings are not considered for now but contain a significant amount of weights (around 30%) for GPT2. They will be considered in a future version of TorusML.
Training Results Visualization
LoRA Fine-tuning Quantized Loss Comparison
- FP32: Full precision (32-bit floating point) baseline training
- ST-ST: Static per-Tensor quantization with fixed ranges
- Input: Static per-Tensor quantization
- Weight: Static per-Tensor quantization
- DTen-ST: Dynamic/Static hybrid quantization
- Input: Dynamic per-Tensor quantization
- Weight: Static per-Tensor quantization
- DTok-SC: Dynamic quantization with finer granularity
- Input: Dynamic per-Token quantization
- Weight: Static per-Channel quantization
Final Training Losses (Step 2500)
| Model Configuration | Final Loss |
|---|---|
| 8-bit (ST-ST) | 2.1290 |
| 16-bit (ST-ST) | 0.4776 |
| 8-bit (DTen-ST) | 0.4215 |
| 16-bit (DTen-ST) | 0.2681 |
| FP32 (Baseline) | 0.2670 |
| 8-bit (DTok-SC) | 0.2688 |
Dynamic quantization is necessary in the backpropagation step to avoid gradient explosion. And per-token / per-channel quantization makes the 8-bit models match the performance of the 32-bit models.
Conclusion
This project showcases the potential of combining LoRA and FHE to fine-tune language models in a privacy-preserving manner. By following the steps outlined in the notebook, you can adapt this approach to your own data-sets and use cases.