Tutorial Lengkap Pinecone: Vector Database untuk AI dan Semantic Search

# Tutorial Lengkap Pinecone: Vector Database untuk AI dan Semantic Search Pinecone adalah managed vector database yang dirancang khusus untuk menyimpan, mengindeks, dan melakukan pencarian similarity...

By Ruby Abdullah · · tutorial
PineconeVector DatabaseRAGSemantic SearchPython

Tutorial Lengkap Pinecone: Vector Database untuk AI dan Semantic Search

Pinecone adalah managed vector database yang dirancang khusus untuk menyimpan, mengindeks, dan melakukan pencarian similarity pada data vektor berdimensi tinggi. Dalam ekosistem AI modern, Pinecone menjadi salah satu pilihan utama untuk membangun sistem Retrieval-Augmented Generation (RAG), semantic search, recommendation engine, dan berbagai aplikasi berbasis embedding.

Berbeda dengan database tradisional yang mengandalkan exact match, Pinecone memungkinkan pencarian berdasarkan kemiripan semantik. Ketika Anda mengubah teks, gambar, atau data lainnya menjadi vektor embedding, Pinecone dapat menemukan item yang paling mirip dalam hitungan milidetik, bahkan pada skala miliaran vektor.

Dalam tutorial ini, kita akan mempelajari cara menggunakan Pinecone dari instalasi hingga penggunaan lanjutan, termasuk integrasi dengan model embedding populer dan membangun pipeline RAG yang lengkap.

Mengapa Memilih Pinecone?

Sebelum masuk ke implementasi, ada beberapa alasan mengapa Pinecone menjadi pilihan populer untuk vector database:

  • Fully Managed: Tidak perlu mengelola infrastruktur, scaling, atau maintenance database
  • Performa Tinggi: Pencarian similarity dalam milidetik pada skala besar
  • Serverless Architecture: Model pricing berbasis penggunaan, cocok untuk berbagai skala proyek
  • Metadata Filtering: Kombinasikan vector search dengan filter metadata untuk hasil yang lebih presisi
  • Namespace Support: Isolasi data dalam satu index menggunakan namespace
  • Hybrid Search: Dukungan untuk sparse-dense vector search
  • Ekosistem Integrasi: Kompatibel dengan LangChain, LlamaIndex, Haystack, dan framework AI lainnya
  • Instalasi dan Setup

    Prasyarat

    Pastikan Anda memiliki Python 3.8 atau lebih baru terinstal di sistem Anda.

    Instalasi Pinecone Client

    pip install pinecone-client
    

    Untuk instalasi dengan dependensi tambahan yang berguna:

    pip install pinecone-client sentence-transformers openai python-dotenv
    

    Membuat Akun dan API Key

  • Daftar akun gratis di pinecone.io
  • Setelah login, buka dashboard dan salin API Key Anda
  • Simpan API Key dengan aman, misalnya di file .env
  • # .env
    

    PINECONEAPIKEY=your-api-key-here

    Inisialisasi Client

    import os
    

    from dotenv import loaddotenv

    from pinecone import Pinecone

    loaddotenv()

    pc = Pinecone(apikey=os.getenv("PINECONEAPIKEY"))

    Verifikasi koneksi

    print("Indexes yang tersedia:", pc.listindexes().names())

    Konsep Dasar Pinecone

    Index

    Index adalah unit penyimpanan utama di Pinecone, mirip dengan "table" di database relasional. Setiap index dikonfigurasi dengan dimensi vektor tertentu dan metrik similarity.

    Namespace

    Namespace memungkinkan Anda mempartisi data dalam satu index. Setiap namespace bersifat independen, sehingga query pada satu namespace tidak akan mengembalikan hasil dari namespace lain.

    Vektor dan Metadata

    Setiap record di Pinecone terdiri dari:

    • ID: Identifier unik untuk vektor
    • Values: Array numerik (vektor embedding)
    • Metadata: Data tambahan berupa key-value pairs yang dapat difilter

    Metrik Similarity

    Pinecone mendukung tiga metrik:

    • Cosine: Mengukur sudut antara dua vektor (paling umum untuk teks)
    • Euclidean: Mengukur jarak geometris antara dua titik
    • Dot Product: Mengukur proyeksi satu vektor ke vektor lainnya

    Basic Usage

    Membuat Index

    from pinecone import Pinecone, ServerlessSpec
    
    

    pc = Pinecone(apikey=os.getenv("PINECONEAPIKEY"))

    indexname = "tutorial-index"

    if indexname not in pc.listindexes().names():

    pc.createindex(

    name=indexname,

    dimension=384, # Sesuaikan dengan model embedding Anda

    metric="cosine",

    spec=ServerlessSpec(

    cloud="aws",

    region="us-east-1"

    )

    )

    print(f"Index '{indexname}' berhasil dibuat")

    Hubungkan ke index

    index = pc.Index(indexname)

    Lihat statistik index

    print(index.describeindexstats())

    Menyimpan Vektor (Upsert)

    # Upsert vektor sederhana
    

    vectors = [

    {

    "id": "doc-1",

    "values": [0.1, 0.2, 0.3, ...], # 384 dimensi

    "metadata": {

    "title": "Pengantar Machine Learning",

    "category": "tutorial",

    "language": "id"

    }

    },

    {

    "id": "doc-2",

    "values": [0.4, 0.5, 0.6, ...],

    "metadata": {

    "title": "Deep Learning Fundamentals",

    "category": "article",

    "language": "en"

    }

    }

    ]

    index.upsert(vectors=vectors)

    Upsert dengan Embedding Model

    Dalam prakteknya, Anda akan menggunakan model embedding untuk menghasilkan vektor:

    from sentencetransformers import SentenceTransformer
    
    

    model = SentenceTransformer("all-MiniLM-L6-v2")

    documents = [

    {"id": "doc-1", "text": "Machine learning adalah cabang dari kecerdasan buatan", "category": "ai"},

    {"id": "doc-2", "text": "Python adalah bahasa pemrograman yang populer untuk data science", "category": "programming"},

    {"id": "doc-3", "text": "Neural network terinspirasi dari cara kerja otak manusia", "category": "ai"},

    {"id": "doc-4", "text": "Database relasional menggunakan tabel untuk menyimpan data", "category": "database"},

    {"id": "doc-5", "text": "Natural Language Processing memproses dan memahami bahasa manusia", "category": "ai"},

    ]

    Generate embeddings

    texts = [doc["text"] for doc in documents]

    embeddings = model.encode(texts)

    Siapkan data untuk upsert

    vectorstoupsert = []

    for doc, embedding in zip(documents, embeddings):

    vectorstoupsert.append({

    "id": doc["id"],

    "values": embedding.tolist(),

    "metadata": {

    "text": doc["text"],

    "category": doc["category"]

    }

    })

    Upsert ke Pinecone

    index.upsert(vectors=vectorstoupsert)

    print(f"Berhasil menyimpan {len(vectorstoupsert)} vektor")

    Melakukan Query (Pencarian Similarity)

    # Query menggunakan teks
    

    querytext = "Bagaimana cara kerja artificial intelligence?"

    queryembedding = model.encode(querytext).tolist()

    results = index.query(

    vector=queryembedding,

    topk=3,

    includemetadata=True

    )

    print(f"Query: {querytext}\n")

    for match in results["matches"]:

    print(f"Score: {match['score']:.4f}")

    print(f"Text: {match['metadata']['text']}")

    print(f"Category: {match['metadata']['category']}")

    print()

    Output:

    Query: Bagaimana cara kerja artificial intelligence?
    
    

    Score: 0.7823

    Text: Machine learning adalah cabang dari kecerdasan buatan

    Category: ai

    Score: 0.6541

    Text: Neural network terinspirasi dari cara kerja otak manusia

    Category: ai

    Score: 0.6102

    Text: Natural Language Processing memproses dan memahami bahasa manusia

    Category: ai

    Query dengan Metadata Filter

    # Hanya cari dalam kategori tertentu
    

    results = index.query(

    vector=queryembedding,

    topk=3,

    includemetadata=True,

    filter={

    "category": {"$eq": "programming"}

    }

    )

    Filter dengan kondisi kompleks

    results = index.query(

    vector=queryembedding,

    topk=5,

    includemetadata=True,

    filter={

    "$and": [

    {"category": {"$in": ["ai", "programming"]}},

    {"language": {"$eq": "id"}}

    ]

    }

    )

    Operasi CRUD Lainnya

    # Fetch vektor berdasarkan ID
    

    fetched = index.fetch(ids=["doc-1", "doc-2"])

    print(fetched)

    Update metadata vektor

    index.update(

    id="doc-1",

    setmetadata={"category": "machine-learning", "updated": True}

    )

    Hapus vektor berdasarkan ID

    index.delete(ids=["doc-4"])

    Hapus berdasarkan filter metadata

    index.delete(filter={"category": {"$eq": "deprecated"}})

    Hapus semua vektor dalam namespace

    index.delete(deleteall=True, namespace="old-data")

    Advanced Usage

    Batch Upsert untuk Data Besar

    Ketika bekerja dengan dataset besar, sebaiknya upsert dilakukan dalam batch:

    import itertools
    
    

    def chunks(iterable, batchsize=100):

    it = iter(iterable)

    chunk = list(itertools.islice(it, batchsize))

    while chunk:

    yield chunk

    chunk = list(itertools.islice(it, batchsize))

    Misalkan Anda punya ribuan dokumen

    largedataset = [...] # List of documents

    allvectors = []

    for i, doc in enumerate(largedataset):

    embedding = model.encode(doc["text"]).tolist()

    allvectors.append({

    "id": f"doc-{i}",

    "values": embedding,

    "metadata": {"text": doc["text"], "source": doc["source"]}

    })

    Upsert dalam batch

    for batch in chunks(allvectors, batchsize=100):

    index.upsert(vectors=batch)

    print(f"Total vektor yang diupsert: {len(allvectors)}")

    Menggunakan Namespace

    # Simpan data ke namespace berbeda
    

    index.upsert(

    vectors=productvectors,

    namespace="products"

    )

    index.upsert(

    vectors=articlevectors,

    namespace="articles"

    )

    Query pada namespace tertentu

    results = index.query(

    vector=queryembedding,

    topk=5,

    namespace="products",

    includemetadata=True

    )

    Statistik per namespace

    stats = index.describeindexstats()

    print(stats)

    {'dimension': 384, 'namespaces': {'products': {'vectorcount': 1000}, 'articles': {'vectorcount': 500}}}

    Membangun RAG Pipeline dengan Pinecone

    Berikut contoh lengkap membangun sistem RAG menggunakan Pinecone dan OpenAI:

    import os
    

    from pinecone import Pinecone, ServerlessSpec

    from openai import OpenAI

    from sentencetransformers import SentenceTransformer

    Inisialisasi

    pc = Pinecone(apikey=os.getenv("PINECONEAPIKEY"))

    openaiclient = OpenAI(apikey=os.getenv("OPENAIAPIKEY"))

    embedmodel = SentenceTransformer("all-MiniLM-L6-v2")

    INDEXNAME = "rag-knowledge-base"

    NAMESPACE = "documents"

    Buat index jika belum ada

    if INDEXNAME not in pc.listindexes().names():

    pc.createindex(

    name=INDEXNAME,

    dimension=384,

    metric="cosine",

    spec=ServerlessSpec(cloud="aws", region="us-east-1")

    )

    index = pc.Index(INDEXNAME)

    def ingestdocuments(documents):

    """Ingest dokumen ke Pinecone"""

    vectors = []

    for i, doc in enumerate(documents):

    # Chunking sederhana

    textchunks = splittext(doc["content"], chunksize=500, overlap=50)

    for j, chunk in enumerate(textchunks):

    embedding = embedmodel.encode(chunk).tolist()

    vectors.append({

    "id": f"{doc['id']}-chunk-{j}",

    "values": embedding,

    "metadata": {

    "text": chunk,

    "source": doc["source"],

    "title": doc["title"]

    }

    })

    # Batch upsert

    for k in range(0, len(vectors), 100):

    batch = vectors[k:k+100]

    index.upsert(vectors=batch, namespace=NAMESPACE)

    return len(vectors)

    def splittext(text, chunksize=500, overlap=50):

    """Split teks menjadi chunk dengan overlap"""

    words = text.split()

    chunks = []

    for i in range(0, len(words), chunksize - overlap):

    chunk = " ".join(words[i:i + chunksize])

    if chunk:

    chunks.append(chunk)

    return chunks

    def retrievecontext(query, topk=5):

    """Retrieve konteks relevan dari Pinecone"""

    queryembedding = embedmodel.encode(query).tolist()

    results = index.query(

    vector=queryembedding,

    topk=topk,

    includemetadata=True,

    namespace=NAMESPACE

    )

    contexts = []

    for match in results["matches"]:

    if match["score"] > 0.3: # Threshold minimum

    contexts.append({

    "text": match["metadata"]["text"],

    "source": match["metadata"]["source"],

    "score": match["score"]

    })

    return contexts

    def generateanswer(query, contexts):

    """Generate jawaban menggunakan LLM dengan konteks dari Pinecone"""

    contexttext = "\n\n".join([

    f"[Source: {ctx['source']}]\n{ctx['text']}"

    for ctx in contexts

    ])

    response = openaiclient.chat.completions.create(

    model="gpt-4o-mini",

    messages=[

    {

    "role": "system",

    "content": (

    "Anda adalah asisten yang menjawab pertanyaan berdasarkan konteks yang diberikan. "

    "Jawab hanya berdasarkan informasi dalam konteks. "

    "Jika informasi tidak tersedia dalam konteks, katakan bahwa Anda tidak menemukan informasinya."

    )

    },

    {

    "role": "user",

    "content": f"Konteks:\n{contexttext}\n\nPertanyaan: {query}"

    }

    ],

    temperature=0.1

    )

    return response.choices[0].message.content

    def ragquery(query):

    """Pipeline RAG lengkap"""

    print(f"Query: {query}")

    # Retrieve

    contexts = retrievecontext(query)

    print(f"Ditemukan {len(contexts)} konteks relevan")

    # Generate

    answer = generateanswer(query, contexts)

    print(f"\nJawaban: {answer}")

    # Sertakan sumber

    print("\nSumber:")

    for ctx in contexts:

    print(f" - {ctx['source']} (score: {ctx['score']:.4f})")

    return answer

    Contoh penggunaan

    knowledgebase = [

    {

    "id": "kb-1",

    "title": "Panduan Python",

    "source": "docs/python-guide.md",

    "content": "Python adalah bahasa pemrograman tingkat tinggi yang mudah dipelajari..."

    },

    {

    "id": "kb-2",

    "title": "Machine Learning Basics",

    "source": "docs/ml-basics.md",

    "content": "Machine learning adalah subset dari artificial intelligence..."

    }

    ]

    Ingest

    count = ingestdocuments(knowledgebase)

    print(f"Berhasil ingest {count} chunks")

    Query

    answer = ragquery("Apa itu machine learning?")

    Hybrid Search (Sparse-Dense)

    Pinecone mendukung hybrid search yang menggabungkan semantic search (dense vectors) dengan keyword search (sparse vectors):

    from pineconetext.sparse import BM25Encoder
    
    

    Inisialisasi BM25 encoder untuk sparse vectors

    bm25 = BM25Encoder()

    Fit BM25 pada corpus

    corpus = [doc["text"] for doc in documents]

    bm25.fit(corpus)

    Generate sparse dan dense vectors

    query = "machine learning tutorial python"

    Dense embedding

    densevector = embedmodel.encode(query).tolist()

    Sparse embedding (BM25)

    sparsevector = bm25.encodequeries(query)

    Hybrid query

    results = index.query(

    vector=densevector,

    sparsevector=sparsevector,

    topk=10,

    includemetadata=True,

    alpha=0.5 # Balance antara dense dan sparse (0 = sparse only, 1 = dense only)

    )

    Integrasi dengan LangChain

    from langchainpinecone import PineconeVectorStore
    

    from langchaincommunity.embeddings import HuggingFaceEmbeddings

    from langchain.textsplitter import RecursiveCharacterTextSplitter

    from langchaincommunity.documentloaders import TextLoader

    Load dokumen

    loader = TextLoader("knowledgebase.txt")

    documents = loader.load()

    Split dokumen

    textsplitter = RecursiveCharacterTextSplitter(

    chunksize=1000,

    chunkoverlap=200

    )

    docs = textsplitter.splitdocuments(documents)

    Embedding model

    embeddings = HuggingFaceEmbeddings(

    modelname="all-MiniLM-L6-v2"

    )

    Buat vector store

    vectorstore = PineconeVectorStore.fromdocuments(

    documents=docs,

    embedding=embeddings,

    indexname="langchain-index",

    namespace="docs"

    )

    Similarity search

    results = vectorstore.similaritysearch(

    "Apa itu neural network?",

    k=3

    )

    for doc in results:

    print(doc.pagecontent)

    print()

    Gunakan sebagai retriever

    retriever = vectorstore.asretriever(

    searchtype="similarity",

    searchkwargs={"k": 5}

    )

    Integrasi dengan LlamaIndex

    from llamaindex.core import VectorStoreIndex, SimpleDirectoryReader
    

    from llamaindex.vectorstores.pinecone import PineconeVectorStore

    from pinecone import Pinecone

    pc = Pinecone(apikey=os.getenv("PINECONEAPIKEY"))

    pineconeindex = pc.Index("llamaindex-demo")

    Buat vector store

    vectorstore = PineconeVectorStore(pineconeindex=pineconeindex)

    Load dan index dokumen

    documents = SimpleDirectoryReader("./data").loaddata()

    index = VectorStoreIndex.fromdocuments(

    documents,

    vectorstore=vectorstore

    )

    Query

    queryengine = index.asqueryengine()

    response = queryengine.query("Jelaskan konsep transfer learning")

    print(response)

    Best Practices

    1. Pilih Dimensi Embedding yang Tepat

    Dimensi embedding harus sesuai dengan model yang Anda gunakan:

    | Model | Dimensi | Kasus Penggunaan |

    |-------|---------|-----------------|

    | all-MiniLM-L6-v2 | 384 | General purpose, ringan |

    | text-embedding-3-small | 1536 | OpenAI, keseimbangan performa-biaya |

    | text-embedding-3-large | 3072 | OpenAI, akurasi maksimal |

    | BAAI/bge-large-en-v1.5 | 1024 | Open source, performa tinggi |

    2. Strategi Chunking yang Efektif

    from langchain.textsplitter import RecursiveCharacterTextSplitter
    
    

    splitter = RecursiveCharacterTextSplitter(

    chunksize=512,

    chunkoverlap=50,

    separators=["\n\n", "\n", ". ", " ", ""]

    )

    Chunk yang terlalu kecil kehilangan konteks

    Chunk yang terlalu besar mengaburkan relevansi

    256-1024 token adalah range yang baik untuk kebanyakan kasus

    3. Manfaatkan Metadata Filter

    # Simpan metadata yang berguna untuk filtering
    

    vector = {

    "id": "article-123",

    "values": embedding,

    "metadata": {

    "text": chunktext,

    "source": "blog",

    "date": "2026-01-15",

    "language": "id",

    "category": "tutorial",

    "author": "Ruby Abdullah"

    }

    }

    Kombinasikan vector search dengan metadata filter

    results = index.query(

    vector=queryembedding,

    topk=10,

    filter={

    "$and": [

    {"category": {"$eq": "tutorial"}},

    {"language": {"$eq": "id"}}

    ]

    },

    includemetadata=True

    )

    4. Monitoring dan Observability

    # Periksa statistik index secara berkala
    

    stats = index.describeindexstats()

    print(f"Total vectors: {stats['totalvectorcount']}")

    print(f"Dimensi: {stats['dimension']}")

    for ns, nsstats in stats.get("namespaces", {}).items():

    print(f"Namespace '{ns}': {nsstats['vectorcount']} vectors")

    5. Penanganan Error dan Retry

    import time
    

    from pinecone.exceptions import PineconeException

    def safeupsert(index, vectors, namespace="", maxretries=3):

    for attempt in range(maxretries):

    try:

    index.upsert(vectors=vectors, namespace=namespace)

    return True

    except PineconeException as e:

    if attempt < maxretries - 1:

    waittime = 2 attempt

    print(f"Retry {attempt + 1}/{maxretries} setelah {waittime}s: {e}")

    time.sleep(waittime)

    else:

    raise

    return False

    6. Optimasi Biaya

    • Gunakan serverless index untuk workload yang bervariasi
    • Pilih dimensi embedding yang sesuai kebutuhan (tidak selalu yang terbesar)
    • Manfaatkan namespace alih-alih membuat banyak index
    • Hapus data yang sudah tidak relevan secara berkala
    • Gunakan metadata filter untuk mempersempit pencarian sebelum vector similarity

    Kesalahan Umum yang Harus Dihindari

  • Mismatch dimensi: Pastikan dimensi index sama dengan output model embedding
  • Tidak menyimpan teks asli: Selalu simpan teks asli di metadata agar bisa ditampilkan
  • Chunk terlalu besar: Chunk >1000 token mengurangi presisi retrieval
  • Mengabaikan score threshold: Selalu filter hasil dengan score minimum
  • Upsert tanpa batch: Untuk data besar, selalu gunakan batch upsert
  • Tidak menggunakan namespace**: Campurkan data berbeda jenis tanpa isolasi
  • Kesimpulan

    Pinecone menyediakan solusi vector database yang handal dan mudah digunakan untuk berbagai aplikasi AI. Dari semantic search sederhana hingga pipeline RAG yang kompleks, Pinecone menawarkan performa tinggi tanpa kerumitan mengelola infrastruktur.

    Hal-hal penting yang perlu diingat:

    • Pilih model embedding dan dimensi yang sesuai dengan kebutuhan
    • Manfaatkan metadata filtering untuk mempersempit pencarian
    • Gunakan batch processing untuk operasi pada data besar
    • Terapkan namespace untuk mengorganisir data
    • Monitor penggunaan dan optimasi biaya secara berkala

    Dengan pemahaman dasar dan teknik lanjutan yang dibahas dalam tutorial ini, Anda sudah siap membangun aplikasi AI yang memanfaatkan vector search secara efektif menggunakan Pinecone.

    Artikel Terkait

    Tutorial Lengkap Qdrant: Vector Database untuk Aplikasi AI

    Tutorial Lengkap Qdrant: Vector Database untuk Aplikasi AI Qdrant adalah vector database performa tinggi yang dirancang ...

    Weaviate: Database Vektor dengan AI Modules Terintegrasi

    Weaviate: Database Vektor dengan AI Modules Terintegrasi Weaviate adalah database vektor open-source yang dirancang untu...

    Tutorial Lengkap LlamaIndex: Membangun Aplikasi RAG dengan LLM

    Tutorial Lengkap LlamaIndex: Membangun Aplikasi RAG dengan LLM LlamaIndex adalah framework data yang powerful untuk memb...

    Tutorial Lengkap ChromaDB: Vector Database Sederhana untuk AI

    Tutorial Lengkap ChromaDB: Vector Database Sederhana untuk AI ChromaDB adalah open-source vector database yang dirancang...