Bangun RAG dengan Milvus + Masker PII
PII (Personally Identifiable Information) adalah jenis data sensitif yang dapat digunakan untuk mengidentifikasi individu.
PII Masker, yang dikembangkan oleh HydroX AI, adalah alat sumber terbuka canggih yang dirancang untuk melindungi data sensitif Anda dengan memanfaatkan model AI yang canggih. Baik saat Anda menangani data pelanggan, melakukan analisis data, atau memastikan kepatuhan terhadap peraturan privasi, PII Masker menyediakan solusi yang kuat dan terukur untuk menjaga keamanan informasi Anda.
Dalam tutorial ini, kami akan menunjukkan cara menggunakan PII Masker dengan Milvus untuk melindungi data pribadi dalam aplikasi RAG (Retrieval-Augmented Generation). Dengan menggabungkan kekuatan kemampuan penyembunyian data PII Masker dengan pengambilan data yang efisien dari Milvus, Anda dapat membuat jalur pipa yang aman dan sesuai dengan privasi untuk menangani informasi sensitif dengan penuh percaya diri. Pendekatan ini memastikan aplikasi Anda dilengkapi untuk memenuhi standar privasi dan melindungi data pengguna secara efektif.
Persiapan
Memulai dengan PII Masker
Ikuti panduan instalasi PII Masker untuk menginstal dependensi yang diperlukan dan mengunduh model. Berikut adalah panduan sederhana:
$ git clone https://github.com/HydroXai/pii-masker-v1.git
$ cd pii-masker-v1/pii-masker
Unduh model darihttps://huggingface.co/hydroxai/pii_model_weight, dan ganti dengan file di: pii-masker/output_model/deberta3base_1024/
Ketergantungan dan Lingkungan
$ pip install --upgrade pymilvus openai requests tqdm dataset
Kita akan menggunakan OpenAI sebagai LLM dalam contoh ini. Anda harus menyiapkan kunci api OPENAI_API_KEY sebagai variabel lingkungan.
$ export OPENAI_API_KEY=sk-***********
Kemudian Anda dapat membuat notebook python atau jupyter untuk menjalankan kode berikut.
Menyiapkan data
Mari kita buat beberapa baris palsu yang berisi informasi PII untuk tujuan pengujian atau demonstrasi.
text_lines = [
"Alice Johnson, a resident of Dublin, Ireland, attended a flower festival at Hyde Park on May 15, 2023. She entered the park at noon using her digital passport, number 23456789. Alice spent the afternoon admiring various flowers and plants, attending a gardening workshop, and having a light snack at one of the food stalls. While there, she met another visitor, Mr. Thompson, who was visiting from London. They exchanged tips on gardening and shared contact information: Mr. Thompson's address was 492, Pine Lane, and his cell phone number was +018.221.431-4517. Alice gave her contact details: home address, Ranch 16",
"Hiroshi Tanaka, a businessman from Tokyo, Japan, went to attend a tech expo at the Berlin Convention Center on November 10, 2023. He registered for the event at 9 AM using his digital passport, number Q-24567680. Hiroshi networked with industry professionals, participated in panel discussions, and had lunch with some potential partners. One of the partners he met was from Munich, and they decided to keep in touch: the partner's office address was given as house No. 12, Road 7, Block E. Hiroshi offered his business card with the address, 654 Sakura Road, Tokyo.",
"In an online forum discussion about culinary exchanges around the world, several participants shared their experiences. One user, Male, with the email 2022johndoe@example.com, shared his insights. He mentioned his ID code 1A2B3C4D5E and reference number L87654321 while residing in Italy but originally from Australia. He provided his +0-777-123-4567 and described his address at 456, Flavorful Lane, Pasta, IT, 00100.",
"Another user joined the conversation on the topic of international volunteering opportunities. Identified as Female, she used the email 2023janedoe@example.com to share her story. She noted her 9876543210123 and M1234567890123 while residing in Germany but originally from Brazil. She provided her +0-333-987-6543 and described her address at 789, Sunny Side Street, Berlin, DE, 10178.",
]
Tutupi data dengan PIIMasker
Mari kita inisialisasi objek PIIMasker dan memuat model.
from model import PIIMasker
masker = PIIMasker()
Kita kemudian menutupi PII dari daftar baris teks dan mencetak hasil yang disamarkan.
masked_results = []
for full_text in text_lines:
masked_text, _ = masker.mask_pii(full_text)
masked_results.append(masked_text)
for res in masked_results:
print(res + "\n")
Alice [B-NAME] , a resident of Dublin Ireland attended flower festival at Hyde Park on May 15 2023 [B-PHONE_NUM] She entered the park noon using her digital passport number 23 [B-ID_NUM] [B-NAME] afternoon admiring various flowers and plants attending gardening workshop having light snack one food stalls While there she met another visitor Mr Thompson who was visiting from London They exchanged tips shared contact information : ' s address 492 [I-STREET_ADDRESS] his cell phone + [B-PHONE_NUM] [B-NAME] details home Ranch [B-STREET_ADDRESS]
Hiroshi [B-NAME] [I-STREET_ADDRESS] a businessman from Tokyo Japan went to attend tech expo at the Berlin Convention Center on November 10 2023 . He registered for event 9 AM using his digital passport number Q [B-ID_NUM] [B-NAME] with industry professionals participated in panel discussions and had lunch some potential partners One of he met was Munich they decided keep touch : partner ' s office address given as house No [I-STREET_ADDRESS] [B-NAME] business card 654 [B-STREET_ADDRESS]
In an online forum discussion about culinary exchanges around the world [I-STREET_ADDRESS] several participants shared their experiences [I-STREET_ADDRESS] One user Male with email 2022 [B-EMAIL] his insights He mentioned ID code 1 [B-ID_NUM] [I-PHONE_NUM] reference number L [B-ID_NUM] residing in Italy but originally from Australia provided + [B-PHONE_NUM] [I-PHONE_NUM] described address at 456 [I-STREET_ADDRESS]
Another user joined the conversation on topic of international volunteering opportunities . Identified as Female , she used email 2023 [B-EMAIL] share her story She noted 98 [B-ID_NUM] [I-PHONE_NUM] M [B-ID_NUM] residing in Germany but originally from Brazil provided + [B-PHONE_NUM] [I-PHONE_NUM] described address at 789 [I-STREET_ADDRESS] DE 10 178
Menyiapkan Model Penyematan
Kita menginisialisasi klien OpenAI untuk menyiapkan model penyematan.
from openai import OpenAI
openai_client = OpenAI()
Tentukan fungsi untuk menghasilkan penyematan teks menggunakan klien OpenAI. Kami menggunakan model text-embedding-3-small sebagai contoh.
def emb_text(text):
return (
openai_client.embeddings.create(input=text, model="text-embedding-3-small")
.data[0]
.embedding
)
Hasilkan embedding uji dan cetak dimensi dan beberapa elemen pertama.
test_embedding = emb_text("This is a test")
embedding_dim = len(test_embedding)
print(embedding_dim)
print(test_embedding[:10])
1536
[0.009889289736747742, -0.005578675772994757, 0.00683477520942688, -0.03805781528353691, -0.01824733428657055, -0.04121600463986397, -0.007636285852640867, 0.03225184231996536, 0.018949154764413834, 9.352207416668534e-05]
Memuat data ke dalam Milvus
Membuat Koleksi
from pymilvus import MilvusClient
milvus_client = MilvusClient(uri="./milvus_demo.db")
Adapun argumen dari MilvusClient:
- Menetapkan
urisebagai file lokal, misalnya./milvus.db, adalah metode yang paling mudah, karena secara otomatis menggunakan Milvus Lite untuk menyimpan semua data dalam file ini. - Jika Anda memiliki data dalam skala besar, misalnya lebih dari satu juta vektor, Anda dapat menyiapkan server Milvus yang lebih berkinerja tinggi di Docker atau Kubernetes. Dalam pengaturan ini, gunakan alamat dan port server sebagai uri Anda, misalnya
http://localhost:19530. Jika Anda mengaktifkan fitur autentikasi pada Milvus, gunakan ": " sebagai token, jika tidak, jangan setel token. - Jika Anda ingin menggunakan Zilliz Cloud, layanan cloud yang dikelola sepenuhnya untuk Milvus, sesuaikan
uridantoken, yang sesuai dengan Public Endpoint dan Api key di Zilliz Cloud.
Periksa apakah koleksi sudah ada dan hapus jika sudah ada.
collection_name = "my_rag_collection"
if milvus_client.has_collection(collection_name):
milvus_client.drop_collection(collection_name)
Buat koleksi baru dengan parameter yang ditentukan.
Jika kita tidak menentukan informasi field apa pun, Milvus akan secara otomatis membuat field default id untuk primary key, dan field vector untuk menyimpan data vektor. Bidang JSON yang dicadangkan digunakan untuk menyimpan bidang yang tidak ditentukan skema dan nilainya.
milvus_client.create_collection(
collection_name=collection_name,
dimension=embedding_dim,
metric_type="IP", # Inner product distance
consistency_level="Bounded", # Supported values are (`"Strong"`, `"Session"`, `"Bounded"`, `"Eventually"`). See https://milvus.io/docs/tune_consistency.md#Consistency-Level for more details.
)
Menyisipkan data
Lakukan perulangan melalui baris teks bertopeng, buat penyematan, lalu masukkan data ke dalam Milvus.
Berikut ini adalah bidang baru text, yang merupakan bidang yang tidak ditentukan dalam skema koleksi. Field ini akan secara otomatis ditambahkan ke field dinamis JSON yang dicadangkan, yang dapat diperlakukan sebagai field normal pada level tinggi.
from tqdm import tqdm
data = []
for i, line in enumerate(tqdm(masked_results, desc="Creating embeddings")):
data.append({"id": i, "vector": emb_text(line), "text": line})
milvus_client.insert(collection_name=collection_name, data=data)
Creating embeddings: 100%|██████████| 4/4 [00:01<00:00, 2.60it/s]
{'insert_count': 4, 'ids': [0, 1, 2, 3], 'cost': 0}
Membangun RAG
Mengambil data untuk kueri
Mari tentukan pertanyaan tentang dokumen.
question = "What was the office address of Hiroshi's partner from Munich?"
Cari pertanyaan dalam koleksi dan ambil kecocokan semantik 1 teratas.
search_res = milvus_client.search(
collection_name=collection_name,
data=[
emb_text(question)
], # Use the `emb_text` function to convert the question to an embedding vector
limit=1, # Return top 1 results
search_params={"metric_type": "IP", "params": {}}, # Inner product distance
output_fields=["text"], # Return the text field
)
Mari kita lihat hasil pencarian dari kueri tersebut
import json
retrieved_lines_with_distances = [
(res["entity"]["text"], res["distance"]) for res in search_res[0]
]
print(json.dumps(retrieved_lines_with_distances, indent=4))
[
[
"Hiroshi [B-NAME] [I-STREET_ADDRESS] a businessman from Tokyo Japan went to attend tech expo at the Berlin Convention Center on November 10 2023 . He registered for event 9 AM using his digital passport number Q [B-ID_NUM] [B-NAME] with industry professionals participated in panel discussions and had lunch some potential partners One of he met was Munich they decided keep touch : partner ' s office address given as house No [I-STREET_ADDRESS] [B-NAME] business card 654 [B-STREET_ADDRESS]",
0.6544462442398071
]
]
Gunakan LLM untuk mendapatkan respons RAG
Ubah dokumen yang diambil ke dalam format string.
context = "\n".join(
[line_with_distance[0] for line_with_distance in retrieved_lines_with_distances]
)
Tentukan permintaan sistem dan pengguna untuk Model Lanage.
Catatan: Kami memberi tahu LLM jika tidak ada informasi yang berguna dalam cuplikan, cukup katakan "Saya tidak tahu".
SYSTEM_PROMPT = """
Human: You are an AI assistant. You are able to find answers to the questions from the contextual passage snippets provided. If there are no useful information in the snippets, just say "I don't know".
AI:
"""
USER_PROMPT = f"""
Use the following pieces of information enclosed in <context> tags to provide an answer to the question enclosed in <question> tags.
<context>
{context}
</context>
<question>
{question}
</question>
"""
Gunakan OpenAI ChatGPT untuk menghasilkan respons berdasarkan permintaan.
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": USER_PROMPT},
],
)
print(response.choices[0].message.content)
I don't know.
Di sini kita dapat melihat, karena kita telah mengganti PII dengan topeng, LLM tidak dapat memperoleh informasi PII dalam konteks. Jadi ia menjawab: "Saya tidak tahu." Dengan cara ini, kita dapat secara efektif melindungi privasi pengguna.