🚀 Coba Zilliz Cloud, Milvus yang sepenuhnya terkelola, secara gratis—rasakan performa 10x lebih cepat! Coba Sekarang>>

milvus-logo
LFAI
Beranda
  • Integrasi
    • Lainnya

Membangun RAG pada Arsitektur Arm

CPUArm digunakan secara luas di berbagai aplikasi, termasuk kasus penggunaan pembelajaran mesin (ML) dan kecerdasan buatan (AI) tradisional.

Dalam tutorial ini, Anda akan mempelajari cara membuat aplikasi Retrieval-Augmented Generation (RAG) pada infrastruktur berbasis Arm. Untuk penyimpanan vektor, kami menggunakan Zilliz Cloud, basis data vektor Milvus yang dikelola secara penuh. Zilliz Cloud tersedia di cloud utama seperti AWS, GCP, dan Azure. Dalam demo ini, kami menggunakan Zilliz Cloud yang digunakan di AWS dengan mesin Arm. Untuk LLM, kami menggunakan model Llama-3.1-8B pada CPU server berbasis AWS Arm menggunakan llama.cpp.

Prasyarat

Untuk menjalankan contoh ini, kami sarankan Anda untuk menggunakan AWS Graviton, yang menyediakan cara yang hemat biaya untuk menjalankan beban kerja ML pada server berbasis Arm. Notebook ini telah diuji pada instance AWS Graviton3 c7g.2xlarge dengan sistem Ubuntu 22.04 LTS.

Anda membutuhkan setidaknya empat core dan RAM 8GB untuk menjalankan contoh ini. Konfigurasikan penyimpanan disk hingga setidaknya 32 GB. Kami menyarankan Anda untuk menggunakan instans dengan spesifikasi yang sama atau lebih baik.

Setelah Anda meluncurkan instans, sambungkan ke instans tersebut dan jalankan perintah berikut ini untuk menyiapkan lingkungan.

Instal python pada server:

$ sudo apt update
$ sudo apt install python-is-python3 python3-pip python3-venv -y

Buat dan aktifkan lingkungan virtual:

$ python -m venv venv
$ source venv/bin/activate

Instal dependensi python yang diperlukan:

$ pip install --upgrade pymilvus openai requests langchain-huggingface huggingface_hub tqdm

Memuat Data Offline

Membuat Koleksi

Kami menggunakan Zilliz Cloud yang diterapkan di AWS dengan mesin berbasis Arm untuk menyimpan dan mengambil data vektor. Untuk memulai dengan cepat, cukup daftarkan akun di Zilliz Cloud secara gratis.

Selain Zilliz Cloud, Milvus yang dihosting sendiri juga merupakan opsi (lebih rumit untuk disiapkan). Kita juga dapat menggunakan Milvus Standalone dan Kubernetes pada mesin berbasis ARM. Untuk informasi lebih lanjut tentang instalasi Milvus, silakan lihat dokumentasi instalasi.

Kami menetapkan uri dan token sebagai Public Endpoint dan Api key di Zilliz Cloud.

from pymilvus import MilvusClient

milvus_client = MilvusClient(
    uri="<your_zilliz_public_endpoint>", token="<your_zilliz_api_key>"
)

collection_name = "my_rag_collection"

Periksa apakah koleksi sudah ada dan hapus jika sudah ada.

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 apapun, 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=384,
    metric_type="IP",  # Inner product distance
    consistency_level="Strong",  # Strong consistency level
)

Kami menggunakan jarak hasil kali dalam sebagai jenis metrik default. Untuk informasi lebih lanjut tentang jenis jarak, Anda dapat merujuk ke halaman Metrik Kemiripan

Siapkan data

Kami menggunakan halaman FAQ dari Dokumentasi Milvus 2.4.x sebagai pengetahuan pribadi dalam RAG kami, yang merupakan sumber data yang baik untuk pipa RAG sederhana.

Unduh file zip dan ekstrak dokumen ke folder milvus_docs.

$ wget https://github.com/milvus-io/milvus-docs/releases/download/v2.4.6-preview/milvus_docs_2.4.x_en.zip
$ unzip -q milvus_docs_2.4.x_en.zip -d milvus_docs

Kami memuat semua file penurunan harga dari folder milvus_docs/en/faq. Untuk setiap dokumen, kita cukup menggunakan "# " untuk memisahkan konten dalam file, yang secara kasar dapat memisahkan konten dari setiap bagian utama dari file penurunan harga.

from glob import glob

text_lines = []

for file_path in glob("milvus_docs/en/faq/*.md", recursive=True):
    with open(file_path, "r") as file:
        file_text = file.read()

    text_lines += file_text.split("# ")

Sisipkan data

Kami menyiapkan model penyematan yang sederhana namun efisien, yaitu all-MiniLM-L6-v2 yang dapat mengubah teks menjadi vektor penyematan.

from langchain_huggingface import HuggingFaceEmbeddings

embedding_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")

Lakukan iterasi melalui baris teks, 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 = []

text_embeddings = embedding_model.embed_documents(text_lines)

for i, (line, embedding) in enumerate(
    tqdm(zip(text_lines, text_embeddings), desc="Creating embeddings")
):
    data.append({"id": i, "vector": embedding, "text": line})

milvus_client.insert(collection_name=collection_name, data=data)
Creating embeddings: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 72/72 [00:18<00:00,  3.91it/s]

Meluncurkan Layanan LLM di Arm

Pada bagian ini, kita akan membangun dan meluncurkan layanan llama.cpp pada CPU berbasis Arm.

Model Llama 3.1 & llama.cpp

Model Llama-3.1-8B dari Meta adalah bagian dari keluarga model Llama 3.1 dan bebas digunakan untuk tujuan penelitian dan komersial. Sebelum Anda menggunakan model ini, kunjungi situs web Llama dan isi formulir untuk meminta akses.

llama.cpp adalah proyek C/C++ sumber terbuka yang memungkinkan inferensi LLM yang efisien pada berbagai perangkat keras - baik secara lokal maupun di cloud. Anda dapat dengan mudah meng-host model Llama 3.1 menggunakan llama.cpp.

Unduh dan bangun llama.cpp

Jalankan perintah berikut untuk menginstal make, cmake, gcc, g++, dan alat penting lainnya yang diperlukan untuk membangun llama.cpp dari sumbernya:

$ sudo apt install make cmake -y
$ sudo apt install gcc g++ -y
$ sudo apt install build-essential -y

Anda sekarang siap untuk mulai membangun llama.cpp.

Kloning repositori sumber untuk llama.cpp:

$ git clone https://github.com/ggerganov/llama.cpp

Secara default, llama.cpp dibuat hanya untuk CPU di Linux dan Windows. Anda tidak perlu menyediakan switch tambahan untuk membangunnya untuk CPU Arm tempat Anda menjalankannya.

Jalankan make untuk membangunnya:

$ cd llama.cpp
$ make GGML_NO_LLAMAFILE=1 -j$(nproc)

Periksa apakah llama.cpp telah dibangun dengan benar dengan menjalankan perintah bantuan:

$ ./llama-cli -h

Jika llama.cpp telah dibangun dengan benar, Anda akan melihat opsi bantuan yang ditampilkan. Cuplikan output terlihat seperti ini:

example usage:

    text generation:     ./llama-cli -m your_model.gguf -p "I believe the meaning of life is" -n 128

    chat (conversation): ./llama-cli -m your_model.gguf -p "You are a helpful assistant" -cnv

Anda sekarang dapat mengunduh model menggunakan cli huggingface:

$ huggingface-cli download cognitivecomputations/dolphin-2.9.4-llama3.1-8b-gguf dolphin-2.9.4-llama3.1-8b-Q4_0.gguf --local-dir . --local-dir-use-symlinks False

Format model GGUF, yang diperkenalkan oleh tim llama.cpp, menggunakan kompresi dan kuantisasi untuk mengurangi presisi bobot menjadi bilangan bulat 4-bit, yang secara signifikan mengurangi kebutuhan komputasi dan memori dan membuat Arm CPU efektif untuk inferensi LLM.

Menghitung ulang bobot model

Untuk menghitung ulang, jalankan

$ ./llama-quantize --allow-requantize dolphin-2.9.4-llama3.1-8b-Q4_0.gguf dolphin-2.9.4-llama3.1-8b-Q4_0_8_8.gguf Q4_0_8_8

Ini akan menghasilkan file baru, dolphin-2.9.4-llama3.1-8b-Q4_0_8_8.gguf, yang berisi bobot yang dikonfigurasi ulang yang memungkinkan llama-cli untuk menggunakan dukungan SVE 256 dan MATMUL_INT8.

Kuantisasi ulang ini optimal secara khusus untuk Graviton3. Untuk Graviton2, rekuantisasi optimal harus dilakukan dalam format Q4_0_4_4, dan untuk Graviton4, format Q4_0_4_8 adalah yang paling cocok untuk rekuantisasi.

Memulai Layanan LLM

Anda dapat menggunakan program server llama.cpp dan mengirim permintaan melalui API yang kompatibel dengan OpenAI. Hal ini memungkinkan Anda untuk mengembangkan aplikasi yang berinteraksi dengan LLM beberapa kali tanpa harus berulang kali memulai dan menghentikannya. Selain itu, Anda dapat mengakses server dari mesin lain di mana LLM di-host melalui jaringan.

Mulai server dari baris perintah, dan server akan mendengarkan port 8080:

$ ./llama-server -m dolphin-2.9.4-llama3.1-8b-Q4_0_8_8.gguf -n 2048 -t 64 -c 65536  --port 8080
'main: server is listening on 127.0.0.1:8080 - starting the main loop

Anda juga dapat menyesuaikan parameter LLM yang diluncurkan untuk menyesuaikannya dengan perangkat keras server Anda untuk mendapatkan kinerja yang ideal. Untuk informasi parameter lebih lanjut, lihat perintah llama-server --help.

Jika Anda kesulitan melakukan langkah ini, Anda dapat merujuk ke dokumen resmi untuk informasi lebih lanjut.

Anda telah memulai layanan LLM pada CPU berbasis Arm. Selanjutnya, kita langsung berinteraksi dengan layanan menggunakan OpenAI SDK.

RAG Online

Klien LLM dan Model Penyematan

Kita menginisialisasi klien LLM dan menyiapkan model penyematan.

Untuk LLM, kita menggunakan OpenAI SDK untuk meminta layanan Llama yang telah diluncurkan sebelumnya. Kita tidak perlu menggunakan kunci API apa pun karena ini sebenarnya adalah layanan llama.cpp lokal kita.

from openai import OpenAI

llm_client = OpenAI(base_url="http://localhost:8080/v1", api_key="no-key")

Buatlah penyematan tes dan cetak dimensi dan beberapa elemen pertama.

test_embedding = embedding_model.embed_query("This is a test")
embedding_dim = len(test_embedding)
print(embedding_dim)
print(test_embedding[:10])
384
[0.03061249852180481, 0.013831384479999542, -0.02084377221763134, 0.016327863559126854, -0.010231520049273968, -0.0479842908680439, -0.017313342541456223, 0.03728749603033066, 0.04588735103607178, 0.034405000507831573]

Mengambil data untuk sebuah kueri

Mari kita tentukan sebuah pertanyaan yang sering muncul tentang Milvus.

question = "How is data stored in milvus?"

Cari pertanyaan tersebut dalam koleksi dan ambil 3 kecocokan semantik teratas.

search_res = milvus_client.search(
    collection_name=collection_name,
    data=[
        embedding_model.embed_query(question)
    ],  # Use the `emb_text` function to convert the question to an embedding vector
    limit=3,  # Return top 3 results
    search_params={"metric_type": "IP", "params": {}},  # Inner product distance
    output_fields=["text"],  # Return the text field
)

Mari kita lihat hasil pencarian kueri

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))
[
    [
        " Where does Milvus store data?\n\nMilvus deals with two types of data, inserted data and metadata. \n\nInserted data, including vector data, scalar data, and collection-specific schema, are stored in persistent storage as incremental log. Milvus supports multiple object storage backends, including [MinIO](https://min.io/), [AWS S3](https://aws.amazon.com/s3/?nc1=h_ls), [Google Cloud Storage](https://cloud.google.com/storage?hl=en#object-storage-for-companies-of-all-sizes) (GCS), [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs), [Alibaba Cloud OSS](https://www.alibabacloud.com/product/object-storage-service), and [Tencent Cloud Object Storage](https://www.tencentcloud.com/products/cos) (COS).\n\nMetadata are generated within Milvus. Each Milvus module has its own metadata that are stored in etcd.\n\n###",
        0.6488019824028015
    ],
    [
        "How does Milvus flush data?\n\nMilvus returns success when inserted data are loaded to the message queue. However, the data are not yet flushed to the disk. Then Milvus' data node writes the data in the message queue to persistent storage as incremental logs. If `flush()` is called, the data node is forced to write all data in the message queue to persistent storage immediately.\n\n###",
        0.5974207520484924
    ],
    [
        "What is the maximum dataset size Milvus can handle?\n\n  \nTheoretically, the maximum dataset size Milvus can handle is determined by the hardware it is run on, specifically system memory and storage:\n\n- Milvus loads all specified collections and partitions into memory before running queries. Therefore, memory size determines the maximum amount of data Milvus can query.\n- When new entities and and collection-related schema (currently only MinIO is supported for data persistence) are added to Milvus, system storage determines the maximum allowable size of inserted data.\n\n###",
        0.5833579301834106
    ]
]

Gunakan LLM untuk mendapatkan respons RAG

Ubah dokumen yang diambil menjadi format string.

context = "\n".join(
    [line_with_distance[0] for line_with_distance in retrieved_lines_with_distances]
)
Define system and user prompts for the Language Model. This prompt is assembled with the retrieved documents from Milvus.

SYSTEM_PROMPT = """
Human: You are an AI assistant. You are able to find answers to the questions from the contextual passage snippets provided.
"""
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 LLM untuk menghasilkan respons berdasarkan petunjuk. Kami menetapkan parameter model menjadi not-used karena parameter ini merupakan parameter yang berlebihan untuk layanan llama.cpp.

response = llm_client.chat.completions.create(
    model="not-used",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": USER_PROMPT},
    ],
)
print(response.choices[0].message.content)

Milvus stores data in two types: inserted data and metadata. Inserted data, including vector data, scalar data, and collection-specific schema, are stored in persistent storage as incremental log. Milvus supports multiple object storage backends such as MinIO, AWS S3, Google Cloud Storage (GCS), Azure Blob Storage, Alibaba Cloud OSS, and Tencent Cloud Object Storage (COS). Metadata are generated within Milvus and each Milvus module has its own metadata that are stored in etcd.

Selamat! Anda telah membangun aplikasi RAG di atas infrastruktur berbasis Arm.

Coba Milvus yang Dikelola secara Gratis

Zilliz Cloud bebas masalah, didukung oleh Milvus dan 10x lebih cepat.

Mulai
Umpan balik

Apakah halaman ini bermanfaat?